标签:生成 状态码 none random 僵尸 单位 bsp 高效 隔离 进程理论: 程序:存放在硬盘上的一大堆代码,其状态是"死"的 进程:程序正在运行的过程,其状态是"活"的 2. 进程调度算法 对于多个进程的执行,都需要抢占CPU资源,而对于CPU仅存在一个的情况下,就需要使用进程调度算法来合理分配CPU资源 先来先服务调度算法 对于多个进程,按照先获取到CPU资源,就先执行的方式,再将该进程的任务完全执行后(包括IO操作),才会去执行下一个进程 缺点:无法合理分配CPU资源,对于重要任务/进程,会因为没有抢占到CPU资源,从而延误 短作业优先调度算法: 对于进程的作业,处理及会计算出该进程的长度,从而根据长度来优先执行短的进程任务 缺点:长作业会因为频繁的短作业从而一直得不到CPU资源 时间片轮转调度算法: 将CPU的处理时间划分成一个一个固定大小的时间片,时间片单位可以是几十毫秒之类,对不同的进程分配不同数量的时间片 如果一个进程在被调度选中后,所分配的时间片执行完毕后,还未执行完任务,那么进程重新回到就绪队列,等待调度分配 缺点:无法合理分配任务优先级 1. 进程时间片用完,任务未执行完毕 2. 进程时间片没用完,因为IO操作从而退出到就绪队列 3. 新创建的高优先级进程,无法立刻被执行 多级反馈队列调度算法: 将CPU的处理时间分成多个队列,例如:高、中、低,其中高优先级队列的时间是中优先级队列的一半,以此类推 对于多个进程,按照先入先出调度算法,进入高优先级队列,如果进程任务能够执行完毕,则释放资源,如果高优先级队列完毕进程任务依然无法执行完毕,则分配到中优先级队列 对于高优先级队列中存在进程,那么立马退出中、低优先级队列,继而执行高优先级队列中的进程 缺点:先入先出调度算法无法合理分配每个队列的资源 时间片轮转+多级反馈队列 将每个队列分成一个一个固定大小的时间片,然后按照调度算法分配给需要CPU资源的进程,再按照多级反馈队列机制来执行 3. 进程的三状态图 创建 --提交--> 就绪态Ready --进程调度--> 运行态Running --释放--> 退出 运行态Running --进程任务未执行完毕--> 就绪态Ready 运行态Running --进程任务中途触发事件--> 阻塞态Blocked 阻塞态Blocked --事件执行完毕--> 就绪态Ready 事件:IO操作,请求缓冲区满等 就绪态Ready:进程已经获取到除CPU资源以外的所有必要资源 运行态Running:进程已经获取到CPU资源,开始执行任务 阻塞态Blocked:进程任务中途触发事件,从而释放资源,等待事件执行完毕 4. 同步和异步 同步:任务提交后,原地阻塞,等待任务返回结果 异步:任务提交后,不会原地阻塞(通过回调机制/函数,获取到返回结果),直接执行其他任务 5. 阻塞和非阻塞 阻塞:即处于进程运行三状态中的阻塞态 非阻塞:即处于进程运行三状态中的就绪态或运行态 最高效的组合:异步+非阻塞 我们自己编写脚本,理想状态就是脚本一直处于就绪态和运行态 进程操作: 1. 创建进程的两种方式 使用Process实例化 from multiprocessing import Process def xxx(self, a): if __name__ == ‘__main__‘: p = Process(target=xxx, args=(a, )) p.start() 类的继承 class xxx(Process): def run(self): # 自动调用 函数体 if __name__ == ‘__main__‘: p.start 2. Process类 from multiprocessing import Process p = Process( target=函数名, args=(位置参数) kwargs={关键字参数} name=进程别名 group=None # 未使用 ) Process类属性: p.name 获取name参数,如果没有,则使用Process-N,N以1开始 p.pid 获取进程id p.daemon 默认为False,True代表开启守护进程 p.exitcode 获取进程退出状态码,如果进程正在运行则返回None,否则返回退出状态码(正常退出返回0) p.authkey 获取身份验证32位bytes,是通过os.urandom(32)随机生成的,用于底层身份验证 Process类方法: p.start() 创建/启动 进程 p.join([timout]) 主进程等待子进程执行结束,并调用wait方法回收子进程资源 p.is_alive() 返回bool值,如果子进程存活返回True p.terminate() 强行终止子进程 current_process().pid 获取当前进程id 3. 进程间通信(IPC) 默认进程间不可通信,进程间相互隔离,这体现在内存空间上的隔离 不同进程存储各自的全局变量,进程间不会共享全局变量 实现进程间通信有两种方法: Queue队列 = 管道+锁 管道 Queue类 from multiprocessing import Queue Queue类按照先入先出算法,对于队列中的数据,先放入的就会被先取出 Queue类的方法 q = Queue([int]) int代表队列长度,不填默认最大 q.qsize() 获取当前队列长度 q.empty() 如果队列位空返回True q.full() 如果队列为空返回False q.put(obj, block=True, timeout=None) q.put_nowait() q.get(block=True,timeout=None) q.get_nowait() 参数讲解: block:设置是否阻塞,False不阻塞,直接报错,put报错queue.Full,get报错queue.Empty timeout:只有当block=True才有效,值为None代表无限大,一直原地阻塞,可以设置秒数,超过该值则直接报错 xx_nowait() 相当于block=False JoinableQueue(Queue)继承于Queue类,且新增两个方法 .join() .task_done() JoinableQueue类存在一个计数器,当调用一次put方法时计数器+1,当调用一次task_done方法时,计数器-1 当计数器为0时,join方法停止阻塞,否则一直阻塞当前进程 Pipe类 Pipe类的实例化需要在进程创建代码之前,然后作为参数传递给进程对象 a, b =Pipe([duplex]) duplex=True 全双工 duplex=False 半双工 a.send(obj) b.recv() a.close() recv方法会阻塞程序,如果管道中没有数据,则会一直阻塞等待数据 如果管道对端关闭端口,则会抛出EOFError异常 本端端口也要关闭端口 在windows中创建进程,需要将创建进程代码写入__name__语句中 因为,在windows中创建进程,默认会使用import类似的方法将本模块的代码导入到子进程中 因此,如果不加__name__语句,则会不停递归创建进程,从而引发错误 僵尸进程 当子进程运行结束后,会留下一个Zombie僵尸进程的数据结构,该数据结构中包含进程ID、运行时间、退出状态等信息 该Zombie数据结构会一直占用进程资源,只有当父进程调用wait/waitpid方法查看子进程的状态信息时,才会回收进程资源 如果父进程存在循环,从而不能及时调用wait/waitpid方法,或者父进程突然死亡,那么就会一直留下僵尸进程,损耗进程资源 孤儿进程 当父进程创建子进程后,突然死亡,此刻子进程还没有运行完毕,那么这就是一个孤儿进程 在linux中,孤儿进程都会被init进程1收养,init进程会不停循环调用wait方法 因此,当孤儿进程任务执行完毕后,会被立刻回收进程资源 守护进程 守护进程会随着父进程的结束而终结 守护进程不能继续创建子进程 from multiprocessing import Process p = Process() p.daemon = True开启守护进程 互斥锁 如果存在多个进程对一个公共资源的访问、修改时,就极容易出现数据错误 此刻就需要加锁处理,将并行变为串行,牺牲效率换取数据安全 from multiprocessing import Lock mutex = Lock() mutex.acquire() 加锁 mutex.release() 释放锁 2021/6/4 并发编程-进程 标签:生成 状态码 none random 僵尸 单位 bsp 高效 隔离 原文地址:https://www.cnblogs.com/zhangzhuowei/p/14851806.html
1. 进程和程序
函数体
p = xxx()
发表评论 取消回复