Python 进程操作之同步控制--锁

网友投稿 595 2022-05-29

进程同步(multiprocess.Lock)

锁 —— multiprocess.Lock

通过刚刚的学习,我们千方百计实现了程序的异步,让多个任务可以同时在几个进程中并发处理,他们之间的运行没有顺序,一旦开启也不受我们控制。尽管并发编程让我们能更加充分的利用IO资源,但是也给我们带来了新的问题。

当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题。

Python 进程操作之同步控制--锁

多进程抢占输出资源:

import os import time import random from multiprocessing import Process def work(n):     print('%s: %s is running' %(n,os.getpid()))     time.sleep(random.random())     print('%s:%s is done' %(n,os.getpid())) if __name__ == '__main__':     for i in range(3):         p=Process(target=work,args=(i,))         p.start()

使用锁维护执行秩序:

# 由并发变成了串行,牺牲了运行效率,但避免了竞争 import os import time import random from multiprocessing import Process,Lock def work(lock,n):     lock.acquire()     print('%s: %s is running' % (n, os.getpid()))     time.sleep(random.random())     print('%s: %s is done' % (n, os.getpid()))     lock.release() if __name__ == '__main__':     lock=Lock()     for i in range(3):         p=Process(target=work,args=(lock,i))         p.start()

上面这种情况虽然使用加锁的形式实现了顺序的执行,但是程序又重新变成串行了,这样确实会浪费了时间,却保证了数据的安全。

接下来,我们以模拟抢票为例,来看看数据安全的重要性。

多进程同时抢购余票:

#文件db的内容为:{"count":1} #注意一定要用双引号,不然json无法识别 #并发运行,效率高,但竞争写同一文件,数据写入错乱 from multiprocessing import Process,Lock import time,json,random def search():     dic=json.load(open('db'))     print('\033[43m剩余票数%s\033[0m' %dic['count']) def get():     dic=json.load(open('db'))     time.sleep(0.1) #模拟读数据的网络延迟     if dic['count'] >0:         dic['count']-=1         time.sleep(0.2) #模拟写数据的网络延迟         json.dump(dic,open('db','w'))         print('\033[43m购票成功\033[0m') def task():     search()     get() if __name__ == '__main__':     for i in range(100): #模拟并发100个客户端抢票         p=Process(target=task)         p.start()

使用锁来保证数据安全:

#文件db的内容为:{"count":5} #注意一定要用双引号,不然json无法识别 #并发运行,效率高,但竞争写同一文件,数据写入错乱 from multiprocessing import Process,Lock import time,json,random def search():     dic=json.load(open('db'))     print('\033[43m剩余票数%s\033[0m' %dic['count']) def get():     dic=json.load(open('db'))     time.sleep(random.random()) #模拟读数据的网络延迟     if dic['count'] >0:         dic['count']-=1         time.sleep(random.random()) #模拟写数据的网络延迟         json.dump(dic,open('db','w'))         print('\033[32m购票成功\033[0m')     else:         print('\033[31m购票失败\033[0m') def task(lock):     search()     lock.acquire()     get()     lock.release() if __name__ == '__main__':     lock = Lock()     for i in range(100): #模拟并发100个客户端抢票         p=Process(target=task,args=(lock,))         p.start()

#加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。 虽然可以用文件共享数据实现进程间通信,但问题是: 1.效率低(共享数据基于文件,而文件是硬盘上的数据) 2.需要自己加锁处理 #因此我们最好找寻一种解决方案能够兼顾:1、效率高(多个进程共享一块内存的数据)2、帮我们处理好锁问题。这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。 队列和管道都是将数据存放于内存中 队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来, 我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。

软件开发 人工智能 云计算 机器学习

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:安装Redis就那么几步,很简单!
下一篇:MySQL 表分区?涨知识了
相关文章