python 39
目录
内容概要
- 进程对象及其他方法
- 僵尸进程与孤儿进程
- 守护进程
- 互斥锁
- 队列介绍
- 进程间通信IPC机制
- 生产者消费者模型
- 线程相关知识点
进程对象及其他方法
如何查看进程的PID号 命令法: windows: tasklist tasklist |findstr PID查看具体的进程 mac: 进入终端之后输入ps aux ps aux|grep PID查看具体的进程 用python功能查看:
from multiprocessing import Process,current_process pid = current_process().pid # 查看当前进程的进程号 p.terminate() # 杀死当前进程,是告诉操作系统帮你去杀死当前进程 但是需要一定的时间 而代码的运行速度极快 p.is_alive() # 判断当前进程是否存活 用OS模块的功能查看: import os os.getpid() # 查看当前进程进程号 os.getppid() # 查看当前进程的父进程进程号
代码实现:
from multiprocessing import Process,current_process import os import time def task(name): print(f‘子进程{name}开始‘) # pid_1 = current_process().pid pid_1 = os.getpid() pid_2 = os.getppid() print(pid_1) print(pid_2) print(f‘子进程运行{name}结束‘) if __name__ == ‘__main__‘: # pid = current_process().pid pid = os.getpid() print(pid,‘主‘) p = Process(target=task, args=(‘1‘,)) p.start() time.sleep(3) # 不能刚运行就杀死该程序 p.terminate() time.sleep(2) print(p.is_alive())
僵尸进程与孤儿进程
# 僵尸进程 """ 死了但是没有死透 当你开设了子进程之后 该进程死后不会立刻释放占用的进程号 因为子进程要让父进程能够查看到它开设的子进程的一些基本信息 占用的pid号 运行时间 父进程会回收子进程占用的pid号等,父进程调用join方法等待子进程运行结束 所有的进程都会步入僵尸进程 危险的僵尸进程: 父进程不死并且在无限制的创建子进程并且子进程也不结束 """ # 孤儿进程 """ 子进程存活,父进程意外死亡 操作系统会开设一个“儿童福利院”专门管理孤儿进程回收相关资源 """
守护进程
该子进程与主进程同生死,只要主进程结束,该守护进程一定会立即终止 方法: p.daemon = True 注意: 将进程p设置成守护进程 这一句一定要放在start方法上面才有效否则会直接报错
互斥锁
多个进程操作同一份数据的时候,会出现数据错乱的问题
针对上述问题,解决方式就是加锁处理:将并发变成串行,牺牲效率但是保证了数据的安全
用法:
调用锁类生成互斥对象
mutex = Lock()
获得该互斥对象 mutex.accquire() 释放该互斥对象 mutex.release()
扩展: 行锁 表锁
注意:
1.锁不能轻易的使用,容易造成死锁现象(我们写代码一般不会用到,都是内部封装好的)
2.锁只在处理数据的部分加来保证数据安全(只在争抢数据的环节加锁处理即可)
代码实现:
def run(i, mutex): search(i) # 给买票环节加锁处理 # 抢锁 mutex.acquire() buy(i) # 操作数据 # 释放锁 mutex.release() if __name__ == ‘__main__‘: # 在主进程中生成一把锁 让所有的子进程抢 谁先抢到谁先买票 mutex = Lock() for i in range(1,11): p = Process(target=run, args=(i, mutex)) p.start()
队列介绍
队列:管道+锁
管道:subprocess
stdin stdout stderr
队列:先进先出
堆栈:先进后出
使用方法:
from multiprocessing import Queue # 创建一个队列 q = Queue # 括号内可以传数字 标示生成的队列最大可以同时存放的数据量 # 往队列中存数据,当队列数据放满了之后 如果还有数据要放程序会阻塞 直到有位置让出来 不会报错 q.put(‘传的值‘) # 去队列中取数据,队列中如果已经没有数据的话 get方法也会原地等待(阻塞)直到有数据为止 v = q.get() v = q.get_nowait() # 没有数据直接报错,信息为:queue.Empty v = q.get(timeout=3) # 没有数据之后原地等待三秒之后再报错,信息为: queue.Empty 其他方法: q.full() # 判断当前队列是否满了 q.empty() # 判断当前队列是否空了 """ q.full() q.empty() q.get_nowait() 在多进程的情况下是不精确,因为下一瞬间队列可能被其他进程操作了 """
代码实现:
from multiprocessing import Queue q = Queue(3) q.put(1) q.put(2) q.put(3) try: print(q.full()) v_1 = q.get() print(v_1) v_2 = q.get() print(v_2) v_3 = q.get() print(v_3) print(q.empty()) v_4 = q.get(timeout=3) print(v_4) except Exception as e: print(‘没有数据了‘)
IPC机制
进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。
这里借助队列通信
使用方法:
同上
代码实现:
from multiprocessing import Queue,Process def producer(q): q.put(‘hello‘) if __name__ == ‘__main__‘: q = Queue() p = Process(target=(producer), args=(q,)) p.start() res = q.get() print(res)
生产者消费者模型
生产者:生产/制造东西的
消费者:消费/处理东西的
该模型除了上述两个之外还需要一个媒介就是 队列
核心思想:
调用JoinableQueue模块用来计数,将消费者设置成守护进程,当q.join()运行时代表队列的数据已全部被消化,此时关闭主进程.
该模块功能:每当你往该队列中存入数据的时候 内部会有一个计数器+1,当你调用task_done的时候 计数器-1
q.join() 当计数器为0的时候 才往后运行
代码实现:
from multiprocessing import JoinableQueue,Process import random import time def producer(x,porducer_name,q,name): for i in range(x): time.sleep(random.randint(1,3)) q.put(name) print(f‘{porducer_name}产生数据{name}‘) def consumer(q,teacher_name): while True: time.sleep(random.randint(1,3)) name=q.get() if name: print(f‘{teacher_name}处理数据{name}‘) q.task_done() if __name__ == ‘__main__‘: q = JoinableQueue() p2 = Process(target=producer,args=(4,‘egon‘,q,‘date‘)) p3 = Process(target=producer,args=(4,‘tank‘,q,‘数据‘)) p1 = Process(target=consumer, args=(q,‘json‘)) p4 = Process(target=consumer, args=(q,‘lili‘)) p2.start() p3.start() p1.daemon = True p4.daemon = True p4.start() p1.start() p2.join() # 如果不等这两个产生者,此时队列里没有数据,守护进程直接被干死了 p3.join() # 如果不等这两个产生者,此时队列里没有数据,守护进程直接被干死了 q.join()