python多线程之死锁现象与递归锁
什么叫死锁现象?当两个线程相互等待对方释放资源时,就会发生死锁。
比如:
from threading import Thread
from threading import Lock
import time
lock_A = Lock()
lock_B = Lock()
class MyThread(Thread):
def run(self):
self.f1()
self.f2()
def f1(self):
lock_A.acquire()
print(f"{self.name}拿到了A锁")
lock_B.acquire()
print(f"{self.name}拿到了B锁")
lock_B.release()
print(f"{self.name}释放了B锁")
lock_A.release()
print(f"{self.name}释放了A锁")
def f2(self):
lock_B.acquire()
print(f"{self.name}拿到了B锁")
time.sleep(0.1)
lock_A.acquire()
print(f"{self.name}拿到了A锁")
lock_A.release()
print(f"{self.name}释放了A锁")
lock_B.release()
print(f"{self.name}释放了B锁")
if __name__ == "__main__":
for i in range(3):
t = MyThread()
t.start()
Thread-1拿到了A锁
Thread-1拿到了B锁
Thread-1释放了B锁
Thread-1释放了A锁
Thread-1拿到了B锁
Thread-2拿到了A锁
thread1 先抢到了A锁,此时t2 t3也想抢A锁,但只能等待,等待t1释放A锁,t1又抢了B锁,此时t1有A B两把锁没有释放 t2 t3 继续等待;当t1依此释放B,A锁时,线程t2,t3 争抢A锁,按照结果分析,t1抢到B锁,t2抢到了A锁,t1拿到了B锁,但是接下来,t1睡了0.1秒,t1拥有着B锁,想要A锁,t2拥有着A锁,想要B锁,这就形成了死锁现象。
递归锁可以解决死锁现象,业务需要多个锁时,先要考虑递归锁:
from threading import Thread
from threading import RLock
import time
lock_A = lock_B = RLock() # 必须这样写
# 这样写不行
# lock_A = RLock
# lock_B = lock_A
# 递归锁有一个计数的功能:原数字为0,上一次锁,计数+1,释放一次锁,计数-1
# 只要递归锁上面的数字不为0,其他线程就不能抢锁
class MyThread(Thread):
def run(self):
self.f1()
self.f2()
def f1(self):
lock_A.acquire()
print(f"{self.name}拿到了A锁")
lock_B.acquire()
print(f"{self.name}拿到了B锁")
lock_B.release()
print(f"{self.name}释放了B锁")
lock_A.release()
print(f"{self.name}释放了A锁")
def f2(self):
lock_B.acquire()
print(f"{self.name}拿到了B锁")
time.sleep(0.1)
lock_A.acquire()
print(f"{self.name}拿到了A锁")
lock_A.release()
print(f"{self.name}释放了A锁")
lock_B.release()
print(f"{self.name}释放了B锁")
if __name__ == "__main__":
for i in range(3):
t = MyThread()
t.start()
Thread-1拿到了A锁
Thread-1拿到了B锁
Thread-1释放了B锁
Thread-1释放了A锁
Thread-1拿到了B锁
Thread-1拿到了A锁
Thread-1释放了A锁
Thread-1释放了B锁
Thread-2拿到了A锁
Thread-2拿到了B锁
Thread-2释放了B锁
Thread-2释放了A锁
Thread-2拿到了B锁
Thread-2拿到了A锁
Thread-2释放了A锁
Thread-2释放了B锁
Thread-3拿到了A锁
Thread-3拿到了B锁
Thread-3释放了B锁
Thread-3释放了A锁
Thread-3拿到了B锁
Thread-3拿到了A锁
Thread-3释放了A锁
Thread-3释放了B锁
Process finished with exit code 0