进程之间的数据不共享,但可共享同一资源,所以访问同一文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争的结果就会产生错乱。
看下面并发打印三个人的信息:
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()
总结: