进程之间的数据不共享,但可共享同一资源,所以访问同一文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争的结果就会产生错乱。
看下面并发打印三个人的信息:
from multiprocessing import Process import random,time def task1(): time.sleep(random.randint(1,3)) print('task1:姓名,xxx') time.sleep(random.randint(1, 3)) print('task1:年龄,34') time.sleep(random.randint(1, 3)) print('task1:性别:男') def task2(): time.sleep(random.randint(1,3)) print('task2:姓名,十三在') time.sleep(random.randint(1, 3)) print('task2:年龄,34') time.sleep(random.randint(1, 3)) print('task2:性别:男') def task3(): time.sleep(random.randint(0, 2)) print('task3:姓名,5王') time.sleep(random.randint(0, 2)) print('task3:年龄,34') time.sleep(random.randint(0, 2)) print('task3:性别:男') if __name__ == '__main__': p1=Process(target=task1) p2=Process(target=task2) p3=Process(target=task3) p1.start() p2.start() p3.start()运行结果如下:
从结果可以看出并发运行,效率虽然高,但并发竞争资源带来了打印信息错乱。
那么如何控制,就是加锁处理。而互斥锁的意思就是互相排斥,我们可以把多个进程比喻多个人,互斥锁的工作原理就是多个人去争抢共同的一个资源:如多个人要上同一个卫生间,一个人抢到卫生间后上一把锁,其他人都有外面等着,等到这个人完成后解锁后,其他人又可以去争夺。所以互斥锁的原题,就是把某一功能并发改串行,虽然降低了效率,但保证了数据安全不错乱。
rom multiprocessing import Process,Lock import random,time def task1(lock): lock.acquire()#获得锁 time.sleep(random.randint(1,3)) print('task1:姓名,xxx') time.sleep(random.randint(1, 3)) print('task1:年龄,34') time.sleep(random.randint(1, 3)) print('task1:性别:男') lock.release()#释放锁 def task2(lock): lock.acquire() time.sleep(random.randint(1,3)) print('task2:姓名,十三在') time.sleep(random.randint(1, 3)) print('task2:年龄,34') time.sleep(random.randint(1, 3)) print('task2:性别:男') lock.release() def task3(lock): lock.acquire() time.sleep(random.randint(0, 2)) print('task3:姓名,5王') time.sleep(random.randint(0, 2)) print('task3:年龄,34') time.sleep(random.randint(0, 2)) print('task3:性别:男') lock.release() if __name__ == '__main__': mutex=Lock() p1=Process(target=task1,args=(mutex,)) p2=Process(target=task2,args=(mutex,)) p3=Process(target=task3,args=(mutex,)) p1.start() p2.start() p3.start()
运行结果如下:
这样子就不会错乱了。
强调:必须是lock.acquire()一次,然后lock.release()释放一次,才能继续lock.acquire(),不能连续的lock.acquire()
互斥锁与join()的区别:
大前提:二者的原理都是一样,都是将并发变成串行,从而保证有序
区别一:join是按照人为指定的顺序执行,而互斥锁是所有进程平等地竞争,谁先抢到谁先执行。
区别二:互斥锁可以让一部分代码(修改共享数据的代码)串行,而join只能将代码整体串行。
来看一个抢票的小例子:
# db.json文件中的内容为{"count": 100} from multiprocessing import Process,Lock import json ,time import random def search(name): dic=json.load(open('db.json','r',encoding='utf-8')) time.sleep(random.randint(0,2))#模拟网络延迟 print('%s查到剩余的票数为%s张'%(name,dic['count'])) def get(name): dic = json.load(open('db.json', 'r', encoding='utf-8')) time.sleep(0.3)#模拟网络延迟 if dic['count']>0: time.sleep(0.1)#模拟网络延迟 print('%s成功买到了剩下的第%s票'%(name,dic['count'])) dic['count'] -= 1 json.dump(dic,open('db.json','w',encoding='utf-8')) def rob_ticket(name ,lock): search(name) with lock: #相当于获得了lock.acquire(),执行代码体完,自动执行lock.release() get(name) if __name__ == '__main__': lock=Lock() for i in range(100): name='路人%s'%i p=Process(target=rob_ticket,args=(name,lock)) p.start()
总结: