Python中多进程深入解析(6)

# 查询
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任务,然后互斥锁却十分符合我们的需求。

互斥锁总结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/942b8ff73ff4d41252705a0d573d82eb.html