互斥锁
进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,
竞争带来的结果就是错乱,如何控制,就是加锁处理
part1:多个进程共享同一打印终端
#并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process,Lock import os,time,random def task(mutex): print("111111") time.sleep(2) print("222222") time.sleep(2) print("333333") if __name__ == "__main__": mutex = Lock() p1 = Process(target=task,args=(mutex,)) p2 = Process(target=task,args=(mutex,)) p3 = Process(target=task,args=(mutex,)) p1.start() p2.start() p3.start() #运行结果 #111111 #111111 #111111 #222222 #222222 #222222 #333333 #333333 #333333
加锁后由并发变成了串行
from multiprocessing import Process,Lock import os,time,random def task(mutex): mutex.acquire() print("111111") time.sleep(2) print("222222") time.sleep(2) print("333333") mutex.release() if __name__ == "__main__": mutex = Lock() p1 = Process(target=task,args=(mutex,)) p2 = Process(target=task,args=(mutex,)) p3 = Process(target=task,args=(mutex,)) p1.start() p2.start() p3.start() #运行结果 #111111 #222222 #333333 #111111 #222222 #333333 #111111 #222222 #333333
互斥锁与join的区别
join是等一个进程运行完后下一个进程才运行,而互斥锁是进程都执行了,不过这个任务每次都只能有一个进程执行,谁抢到谁运行。
且join是全局的,一个进程没完不会开启下一个进程,互斥锁可以局部进行,专门为某一个任务加锁。
#有一个名为db.txt的文件,内容为{"count": 1}
def search(): #查票
with open('db.txt',encoding='utf-8') as f:
dic=json.load(f)
print('%s 剩余票数 %s' %(os.getpid(),dic['count']))
def get(): #买票
with open('db.txt',encoding='utf-8') as read_f:
dic=json.load(read_f)
if dic['count'] > 0:
dic['count']-=1
time.sleep(random.randint(1,3)) #模拟手速+网速
with open('db.txt','w',encoding='utf-8') as write_f:
json.dump(dic,write_f)
print('%s 抢票成功' %os.getpid())
def task():
search()
get()
if __name__ == '__main__':
for i in range(20): #模拟20人买票
p=Process(target=task)
p.start()
p.join()
#运行结果-使用join其他人不能够查票
8596 剩余票数 1
8596 抢票成功
4092 剩余票数 0
9088 剩余票数 0
7508 剩余票数 0
10424 剩余票数 0
3216 剩余票数 0
15432 剩余票数 0
6136 剩余票数 0
5440 剩余票数 0
7744 剩余票数 0
14744 剩余票数 0
14768 剩余票数 0
15812 剩余票数 0
7140 剩余票数 0
10076 剩余票数 0
15364 剩余票数 0
8332 剩余票数 0
16180 剩余票数 0
3052 剩余票数 0
8592 剩余票数 0
使用锁的方式
def search():
with open('db.txt',encoding='utf-8') as f:
dic=json.load(f)
print('%s 剩余票数 %s' %(os.getpid(),dic['count']))
def get():
with open('db.txt',encoding='utf-8') as read_f:
dic=json.load(read_f)
if dic['count'] > 0:
dic['count']-=1
time.sleep(random.randint(1,3)) #模拟手速+网速
with open('db.txt','w',encoding='utf-8') as write_f:
json.dump(dic,write_f)
print('%s 抢票成功' %os.getpid())
def task(mutex):
search()
mutex.acquire()
get() # 只为买票加锁
mutex.release()
if __name__ == '__main__':
mutex=Lock()
for i in range(20):
p=Process(target=task,args=(mutex,))
p.start()
#结果-并不影响查票,但买票只能一个一个买
10356 剩余票数 1
15436 剩余票数 1
10008 剩余票数 1
14496 剩余票数 1
5668 剩余票数 1
15884 剩余票数 1
7288 剩余票数 1
7308 剩余票数 1
15740 剩余票数 1
152 剩余票数 1
12260 剩余票数 1
14988 剩余票数 1
15396 剩余票数 1
15696 剩余票数 1
1036 剩余票数 1
7632 剩余票数 1
15392 剩余票数 1
14600 剩余票数 1
12408 剩余票数 1
16168 剩余票数 1
10356 抢票成功
线程互斥锁
线程之间数据共享,如果多个线程同时修改数据,会产生意外的结果
from threading import Thread,Lock import time n=100 def task(): global n temp=n time.sleep(0.1) #模仿处理时间 n=temp-1 if __name__ == '__main__': # mutex=Lock() t_l=[] for i in range(100): t=Thread(target=task) t_l.append(t) t.start() for t in t_l: t.join() print(n) # 运行结果-他们几乎是同时拿到了数据,进行处理,但拿到的是相同的数据 99
加锁
from threading import Thread,Lock import time n=100 def task(): #可以不传递mutex,线程共享资源,而进程必须要传过去 global n mutex.acquire() temp=n time.sleep(0.1) n=temp-1 mutex.release() #另外一种写法
# global n
# with mutex:
# temp=n
# time.sleep(0.1)
# n=temp-1
if __name__ == '__main__': mutex=Lock() t_l=[] for i in range(100): t=Thread(target=task) t_l.append(t) t.start() for t in t_l: t.join() print(n) #执行结果-进行加锁,使他们不能同时拿到数据,只有在一个进程结束之后才可以拿 #0
死锁与递归锁
所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程

浙公网安备 33010602011771号