互斥锁:牺牲了执行效率而获得数据安全
问题:
# 多个线程抢占资源,会发生数据混乱
from threading import Thread
import os,time
def work():
global n
temp=n
time.sleep(0.1)
n=temp-1
if __name__ == '__main__':
n=100
l=[]
for i in range(100):
p=Thread(target=work)
l.append(p)
p.start()
for p in l:
p.join()
print(n) #结果可能为99
解决:
# 引入锁(Lock)的介入,一把钥匙配一把锁
from threading import Thread,Lock
import os,time
def work():
global n
lock.acquire()
temp=n
time.sleep(0.1)
n=temp-1
lock.release()
if __name__ == '__main__':
lock=Lock()
n=100
l=[]
for i in range(100):
p=Thread(target=work)
l.append(p)
p.start()
for p in l:
p.join()
print(n) #结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全
死锁:
# 这时fork的锁拿到了一些资源,noodle拿到了一些资源,互不相让,造成死锁
import time
from threading import Thread,Lock
fork_lock = noodle_lock = Lock()
fork_lock.acquire()
print(222)
noodle_lock.acquire()
print(333)
fork_lock.release()
noodle_lock.release()
print(111)
递归锁:解决死锁
import time
from threading import Thread,RLock
fork_lock = noodle_lock = RLock()
def eat1(name):
# 死锁就是noodle_lock抢到的钥匙也能打开下面的fork_lock
noodle_lock.acquire()
print('%s 抢到了面条111'%name)
fork_lock.acquire()
print('%s 抢到了叉子222'%name)
print('%s 吃面333'%name)
fork_lock.release()
noodle_lock.release()
def eat2(name):
# 这个相当于跟上面的递归锁是同一级的,所以上面抢到了,这个必须等到上述递归锁的counter为0
# 也就是所有的资源都release掉了之后,才释放资源
fork_lock.acquire()
print('%s 抢到了叉子555' % name)
time.sleep(1)
noodle_lock.acquire()
print('%s 抢到了面条666' % name)
print('%s 吃面777' % name)
noodle_lock.release()
fork_lock.release()
for name in ['哪吒','egon','yuan']:
t1 = Thread(target=eat1,args=(name,))
t2 = Thread(target=eat2,args=(name,))
t1.start()
t2.start()