并发通信Manage,队列, 互斥锁
目录
进程间的通信是被限制的
from multiprocessing import Process a = 1 def func(): global a # 声明全局变量 a = 2 # 修改全局变量 func() print(a) p = Process(target=func) p.start() p.join() print(a)
两个结果,第一个是2,第二个是1-----> 进程内存空间是独立的
解决方案:开辟一个新的进程空间,通过代理器和管理器进行通信
1, 管理器负责与公共进程通信
2, 代理负责操作共享空间
from multiprocessing import Process, Manage(管理器) mgr = Manage() # 先开启一个子进程(守护进程),并且返回一个用来通信的管理器 shared_list = mgr.list() # 通过Manage管理器开启一个公共l列表空间(代理) def func(lis): lis.appent('hello') p = Process(target=func, args=(shared_list, )) p.start(0 p.join() print(shared_list) --> ['hello']
这里需要知道,可以开启的代理空间有以下几个:
mgr.list() 列表
mgr.dict() 字典
mgr.Queue() 队列
队列操作:
入列:put()
出列:get()
测试空:empty() 近似值
测试满:funll() 近似值
队列长度:qsize() 近似值
任务结束: task_done()
等待完成:join()
需要了解的是,队列中存在一个计数器的概念,当put的时候,计数器会加1,当task_done时,计数器减1
可以用join进行测试,当计数器不是0,队列会阻塞,只有当计数器为0时,才会解阻塞
线程间的通信不存在限制,但是会存在资源竞争的问题,即同时执行的线程,公用共享资源的时候,会抢占资源,导致数据乱序
所以需要互斥锁来锁定某些操作
在python的原始解释器Cpython中存在着GIL(Global Interpreter Lock,全局解释器锁)因此在解释器执行Python代码
时,会产生互斥锁来限制线程对共享资源的访问,直到解释器遇到I/O操作或者操作次数达到一定数目才会释放GIL。
import threading from Thread, Lock lock = Lock() # 实例化一个锁 with lock: xxxxxxxx ''' 或者: lock.acquire() # 上锁 xxxxxxxx lock.release() # 解锁 xxxxxx能少则少 锁不能加太多,会大大下降性能 '''
1 from threading import Thread, Lock 2 3 lock = Lock() # 实例化一个锁的实例 4 a = 0 5 6 def incr(n): # 自加 7 global a 8 for i in range(n): 9 with lock: 10 a += 1 11 12 def decr(n): # 自减 13 global a 14 for i in range(n): 15 with lock: 16 a -= 1 17 18 t = Thread(target=incr, args=(1000000, )) 19 t2 = Thread(target=decr, args=(1000000, )) 20 t.start() 21 t2.start() 22 t.join() 23 t2.join() 24 print(a) 25 26 --> 0
如果不加锁,线程之间会竞争资源,得到的结果是一个随机值