# 查询
def search(name):
time.sleep(1)
dic=json.load(open('db.txt','r',encoding='utf-8')) # 在当前目录下db.txt内容:
print('<%s> 查看到剩余票数【%s】' %(name,dic['count']))
# 购票
def get(name):
time.sleep(1)
dic=json.load(open('db.txt','r',encoding='utf-8'))
if dic['count'] > 0:
dic['count']-= 1
time.sleep(3)
json.dump(dic,open('db.txt','w',encoding='utf-8'))
print('<%s> 购票成功' %name)
def task(name):
search(name)
get(name)
if __name__ == '__main__':
for i in range(10):
p=Process(target=task,args=('路人%s' %i,))
p.start()
# 运行结果
<路人2> 查看到剩余票数【1】
<路人0> 查看到剩余票数【1】
<路人3> 查看到剩余票数【1】
<路人4> 查看到剩余票数【1】
<路人1> 查看到剩余票数【1】
<路人8> 查看到剩余票数【1】
<路人5> 查看到剩余票数【1】
<路人9> 查看到剩余票数【1】
<路人6> 查看到剩余票数【1】
<路人7> 查看到剩余票数【1】
<路人2> 购票成功
<路人0> 购票成功
<路人3> 购票成功
<路人4> 购票成功
<路人1> 购票成功
<路人8> 购票成功
<路人5> 购票成功
<路人9> 购票成功
<路人6> 购票成功
<路人7> 购票成功
这样看运行结果的话,肯定是不合理的,票只有一张,怎么会让10个人都购票成功呢?所以这里需要使用互斥锁,互斥锁就是相互排斥,它工作的原理就是把并发变成串行,虽然程序运行效率低了,但是对数据安全和不错乱得到了明显的提升。
from multiprocessing import Process,Lock
import json
import time
def search(name):
time.sleep(1)
dic=json.load(open('db.txt','r',encoding='utf-8'))
print('<%s> 查看到剩余票数【%s】' %(name,dic['count']))
def get(name):
time.sleep(1)
dic=json.load(open('db.txt','r',encoding='utf-8'))
if dic['count'] > 0:
dic['count']-= 1
time.sleep(3)
json.dump(dic,open('db.txt','w',encoding='utf-8'))
print('<%s> 购票成功' %name)
def task(name,lock):
'''
因为在查询的时候看到的余票是一样的,所以需要在购票环节需要添加互斥锁
:param name:
:param lock:
:return:
'''
search(name)
lock.acquire() # 加锁
get(name)
lock.release() # 解锁
if __name__ == '__main__':
# 首先要生成互斥锁对象
lock = Lock()
for i in range(10):
p=Process(target=task,args=('路人%s' %i,lock))
p.start()
# 运行结果为
在上面的代码中,10位用户都看到了剩余的票数,但是只有路人3抢到了票,这就相当于10个人去抢洗手间,但是只有3号用户得到了洗手间的钥匙进去了,并且把洗手间给反锁了。
互斥锁和join的区别
在之前呢,我们讲过了join()方法和互斥锁的概念,让我们来说一下他们之间的区别
join()方法的作用是让主进程等待子进程运行成功之后在再去运行,join()是把并行改成了串行,确实能够保证数据的安全以及不错乱,但是查票的过程中谁先查到票,那么这张票就是谁的。join()就是把所有的任务都变成了串行,如task函数里的search和get。可以比喻成在一段代码中在最上面添加了try,在最下面添加了except。
而互斥锁呢就是相互排斥,在购票环节设置互斥锁,也是将并行改成了串行,但是互斥锁是将程序中的一个任务的某一段代码设置成串行,就比如task函数里的get任务,然后互斥锁却十分符合我们的需求。
互斥锁总结