zoukankan      html  css  js  c++  java
  • 多道技术/进程初识

    多道技术

    1.空间上的复用

    • 多个程序共用一套计算机硬件

    2.时间上的复用

    • 切换+保存状态
      • 1.当一个程序遇到IO操作 操作系统会剥夺该程序的cpu执行权限(提高了cpu的利用率 并且也不影响程序的执行效率)
      • 2.当一个程序长时间占用cpu 操作系统也会剥夺该程序的cpu执行权限(降低了程序的执行效率)
    • 并发:看起来像同时运行的就可以
    • 并行:真正意义上的同时执行
      • 单核的计算机能不能实现并行,但是可以实现并发

    进程的同步与异步

    程序:一坨代码

    进程:正在运行的程序

    同步异步:表示的是任务的提交方式

    • 同步:任务提交之后 原地等待的任务的执行并拿到返回结果才走 期间不做任何事(程序层面的表现就是卡住了)
    • 异步:任务提交之后 不再原地等待 而是继续执行下一行代码(结果是要的 但是是用过其他方式获取)

    阻塞非阻塞:表示的程序的运行状态

    • 阻塞:阻塞态
    • 非阻塞:就绪态 运行态

    强调:同步异步 阻塞非阻塞是两对概念 不能混为一谈


    创建进程的两种方式

    windows创建进程会将代码以模块的方式,从上往下执行一遍

    linux会直接将代码完完整整的拷贝一份,fork一份

    第一种方式:

    • windows创建进程一定要在__main__ 代码块内创建,否则报错

    from muliprocessing import Process
    import time
    ​
    def test(name):
        print('%s is running' %name)
        time.sleep(3)
        print('%s is over' %name)
        
    # windows创建进程一定要在if __name__ == '__main__':代码块内创建,否则报错 
    if __name__ == '__main__':
        p = Process(target=test,args=('egon',))  # 创建一个进程对象
        p.start()  # 告诉操作系统,帮你创建一个进程
        print('')
    #
    # egon is running
    # egon is over

    总结:

    • 创建进程就是在内存中重新开辟一块内存空间,将允许产生的代码丢进去;而且一个进程对应在内存就是一块独立的内存空间
    • 进程与进程之间数据是隔离的,无法直接交互,但是可以通过某些技术实现间接交互

    第二种方式:

    from muliprocessing import Process
    import time
    ​
    class MyProcess(Process):
        def __init__(self,name):
            super().__init__()
            self.name = name
    ​
    def run(self):
        print('%s is running' %self.name)
        time.sleep(3)
        print('%s is over' %self.name)
        
    if __name__ == '__main__':
        p = MyProcess(target=test,args=('egon',))
        p.start()
        print('')
    #
    # egon is running
    # egon is over  

    join方法

    from muliprocessing import Process
    import time
    ​
    def test(name,i):
        print('%s is running' %name)
        time.sleep(i)
        print('%s is over' %name)
        
    if __name__ == '__main__':
        p_list = []
        start_time = time.time()
        for i in range(3):
            p = Process(target=test,args=('进程%s'%i,i))
        # 主进程代码等待字进程运行结束才继续运行
            p.start()  # 仅仅是告诉操作系统帮你创建一个进程,至于先后顺序则是随机的
            p_list.append(p)
        for p in p_list:
            p.join()  # 主进程代码等待子进程运行结束
        print('')
        print(time.time() - start_time)
        # 进程0 is running
        # 进程0 is over
        #
        # 所有步骤花费的时间显示

    进程间数据是隔离的

    from muliprocessing import Process
    import time
    ​
    money = 100  # 主进程内的money
    def test():
        global money
        money = 888888  # 子进程内的money
    if __name__ == '__main__':
        p = Process(target=test)
        p.start()
        p.join()
        print(money)  # 100

    进程对象及其他方法

    在操作系统cmd终端中可以通过tasklist + pid码来查询

    from muliprocessing import Process,current_process
    import os
    import time
    ​
    def test(name):
        print('%s is running' %name,current_process().pid)
        print('%s is running' %name,'子进程%s' %os.getpid(),'父进程%s' %os.getppid())
        time.sleep(30)
        print('%s is over' %name)
    ​
    if __name__ == '__main__':
        p = Process(target=test,args=('egon',))
        p.start()
        p.terminate()  # 杀死当前进程,其实是告诉操作系统帮你杀死一个进程
        time.sleep(0.1)
        print(p.is_alive())  # 判断进程是否存活 返回True:马上杀死,False:已杀死
        print('',current_process().pid)
        print('',os.getpid(),'主主进程:%s' %os.getppid())
        # 主 23040 主主进程:20352
        # egon is running 21991
        # egon is over

    僵尸进程

    父进程回收子进程资源的两种方式

    • 1.join方法
    • 2.父进程正常死亡

    PS:所有的进程都会步入僵尸进程


    孤儿进程

    • 子进程没死,父进程意外死亡
    • 针对linux,会有一个儿童福利院(init),如果父进程意外死亡,他所创建的子进程都会被福利院收养

    守护进程

    from muliprocessing import Process
    import time
    ​
    def test(name):
        print('%s总管正常或者' %name)
        time.sleep(3)
        print('%s总管正常死亡' %name)
        
    if __name__ == '__main__':
        p = Process(target=test,args=('egon',))
        p.daemon = True  # 将该进程设置为守护进程,而且这句话必须放在start语句之前,否则会报错
        p.start()
        print('皇帝jason寿终正寝')
        # 皇帝jason寿终正寝

    互斥锁

    定义:当多个进程操作同一份数据时,会造成数据的错乱,这个时候必须加锁处理,将并发变成串行,虽然降低了效率,但是提高了数据的安全

    注意:

    • 1.锁不要轻易使用,容易造成死锁现象
    • 2.只在处理数据的部分加锁,不要在全局加锁

    设计一个模拟抢票软件

    from muliprocessing import Process,lock
    import time
    import json
    ​
    # 查票
    def search(i):
        with open('data','r',encoding='utf-8') as f:
            data = f.read()
        t_d = json.loads(data)
        print('用户%s查询余票为:%s' %(1,t_d.get('ticket')))
        
    # 买票
    def buy(i):
        with open('data','r',encoding='utf-8') as f:
            data = f.read()
        t_d = json.loads(data)
        time.sleep(1)
        if t_d.get('ticket') > 0:
            # 票数减1
            t_d['ticket'] -= 1
            # 更新票数
            with open('data','w',encoding='utf-8') as f:
                json.dump(t_d,f)
            print('用户%s抢票成功!'%i)
        else:
            print('没票了!)
                  
    def run(i,mutex):
        search(i)
        mutex.acquire()  # 抢锁,只要有人抢到了锁,其他人必须等待该人释放锁
        buy(i)
        mutex.release()  # 释放锁
                  
    if __name__ == '__main__':
        mutex = Lock()  # 生成了一把锁
        for i in range(10):
            p = Process(target=test,args=('egon',))
             p.start()
  • 相关阅读:
    ASP.NET图片上传(配合jquery.from.js 插件)
    判断上传文件类型,上传图片
    父子一对多iframe,子iframe改子iframe元素
    Jquery 清空input file的值
    通过createObjectURL实现图片预览
    URL.createObjectURL() 与 URL.revokeObjectURL()
    python try finally和with语句
    python mixin 模式特点
    Python中的Sentinel(哨兵)值
    《JavaScript ES6 函数式编程入门经典》笔记1
  • 原文地址:https://www.cnblogs.com/zhukaijian/p/11328029.html
Copyright © 2011-2022 走看看