1.锁 —— multiprocessing.Lock
当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题。
from multiprocessing import Process import random import time def func(addr): print('我是%s'%addr) time.sleep(random.random()) print('谢谢!') if __name__ == '__main__': l = ['四川的','湖南的','河南的','江苏的'] for addr in l: p = Process(target=func,args=(addr,)) p.start() time.sleep(2) print('\n\n我选%s'%random.choice(l)) # 关于抢占输出资源的事情,是指多进程并发执行时,并不是一个进程执行完任务后其他进程再执行。 # 比如 此程序会输出:我是四川的 我是河南的 我是江苏的 谢谢!谢谢!我是湖南的 谢谢! 谢谢! # 而不是 : 我是四川的 谢谢! 我是河南的 谢谢! ...
from multiprocessing import Process ,Lock import random import time def func(addr,lock): lock.acquire() print('我是%s'%addr) time.sleep(random.random()) print('谢谢!') lock.release() if __name__ == '__main__': lock = Lock() l = ['四川的','湖南的','河南的','江苏的'] for addr in l: p = Process(target=func,args=(addr,lock)) p.start() time.sleep(4) print('\n\n我选%s'%random.choice(l))
from multiprocessing import Process,Lock import time def check(i): with open('a') as f : num = f.read() print('第%s个人在查票,余票为%s' % (i,num)) def buy(i,l): l.acquire() with open('a') as f : num = int(f.read()) time.sleep(0.1) if num >0 : print('\033[31m 第%s个人买到票了\033[0m'%i) num -= 1 else: print('\033[32m 第%s个人没有买到票\033[0m'%i) time.sleep(0.1) with open('a','w') as f : f.write(str(num)) l.release() if __name__ == "__main__" : l=Lock() for i in range(10): p_ch = Process(target=check,args=(i+1,)) p_ch.start() for i in range(10): p_buy = Process(target=buy,args=(i+1,l)) p_buy.start()
from multiprocessing import Process,Lock,Value import time def get_money(num,l): l.acquire() for i in range(100): num.value -=1 print(num.value) time.sleep(0.01) l.release() def put_money(num,l): l.acquire() for i in range(100): num.value+=1 print(num.value) time.sleep(0.01) l.release() if __name__ =='__main__': num = Value('i',100) l = Lock() p = Process(target=get_money,args=(num,l)) p.start() p1 = Process(target=put_money, args=(num,l)) p1.start() p.join() p1.join() print(num.value)
2.信号量 —— multiprocessing.Semaphore(了解)
上述讲的Lock,属于互斥锁,也就是一把钥匙配备一把锁,同时只允许锁住某一个数据。而信号量则是多把钥匙配备多把锁,也就是说同时允许锁住多个数据。
比如在一个粉红发廊,里边有5位服务人员,那么这个发廊最多就同时允许进入5位客人,当又有第6位客人来的时候,就需要在门外等待;当服务人员服务完某位客人后,才允许后续的人再进来一个,换句话说,这个发廊最多同时接待5位客人,多的客人必须等待。
信号量同步基于内部计数器,用户初始化一个计数器初值(比如上述例子中就初始化为5),每调用一次acquire(),计数器减1;每调用一次release(),计数器加1。当计数器为0时,acquire()调用被阻塞。这是迪科斯彻(Dijkstra)信号量概念P()和V()的Python实现。信号量同步机制适用于访问像服务器这样的有限资源。信号量与进程池的概念很像,但是要区分开,信号量涉及到加锁的概念
from multiprocessing import Process,Semaphore import time import random def func(i,sem): sem.acquire() print('第%s个人进入小黑屋,拿了钥匙锁上门' % i) time.sleep(random.randint(3,5)) print('第%s个人出去小黑屋,还了钥匙打开门' % i) sem.release() if __name__ == '__main__' : sem =Semaphore(5) for i in range(20) : p = Process(target=func,args=(i,sem)) p.start()
3.事件 —— multiprocessing.Event(了解)
#from multiprocessing import Event #e = Event() # e.set() # e.clear() # e.wait() # e.is_set() # 事件是通过is_set()的bool值,去标识e.wait() 的阻塞状态 # 当is_set()的bool值为False时,e.wait()是阻塞状态 # 当is_set()的bool值为True时,e.wait()是非阻塞状态 # 当使用set()时,是把is_set的bool变为True # 当使用clear()时,是把is_set的bool变为False
from multiprocessing import Event, Process import time def tra(e): while 1: if e.is_set(): time.sleep(5) print('\033[31m 红灯亮!\033[0m') e.clear() else: time.sleep(5) print('\033[32m 绿灯亮!\033[0m') e.set() def Car(i, e): e.wait() print('第%s辆车过去了' % i) if __name__ == '__main__': e = Event() triff_light = Process(target=tra, args=(e,)) triff_light.start() for i in range(500): car = Process(target=Car, args=(i + 1, e,)) car.start() time.sleep(2)