立即學習:https://edu.csdn.net/course/play/24458/296445?utm_source=blogtoedu
1.死鎖(Lock()的局限性)
知識點:Lock()只能被獲得(acquire)一次,要想再次獲得必須釋放后才能獲得
?
1)死鎖情況1
#死鎖情況1
from threading import Thread,Lock
import time
#設置了兩把互斥鎖
mutexA = Lock()
mutexB = Lock()class mythread(Thread):def run(self):self.f1()self.f2()def f1(self):#首先線程1獲得了A鎖,再獲得B鎖,最后兩個都釋放,開始進行f2中的B鎖,因為沉睡了0.1秒,足以讓線程2獲得f1中的A鎖,接下來線程1的工作是沉睡結束后獲得A鎖,線程2準備獲得B鎖,一直處于等待鎖的釋放,因為線程1和線程2都是在等待彼此手中的那把鎖,因此形成了死鎖mutexA.acquire()print('%s獲取到了A鎖'%self.name)mutexB.acquire()print('%s獲取到了B鎖'%self.name)mutexB.release()mutexA.release()def f2(self):mutexB.acquire()print('%s獲取到了B鎖'%self.name)time.sleep(0.1)mutexA.acquire()print('%s獲取到了A鎖'%self.name)mutexA.release()mutexB.release()if __name__ == '__main__':#線程切換的速度非常快,因此可以看成是依次線程執行的for i in range(10):t = mythread()t.start()
?
2)死鎖情況2
#死鎖情況2
from threading import Thread,Lock
import time
#設置了兩把互斥鎖,且是同一把鎖
mutexA = mutexB = Lock()class mythread(Thread):def run(self):self.f1()def f1(self):#首先線程1獲得了A鎖,再獲得B鎖,最后兩個都釋放,開始進行f2中的B鎖,因為沉睡了0.1秒,足以讓線程2獲得f1中的A鎖,接下來線程1的工作是沉睡結束后獲得A鎖,線程2準備獲得B鎖,一直處于等待鎖的釋放,因為線程1和線程2都是在等待彼此手中的那把鎖,因此形成了死鎖mutexA.acquire()print('%s獲取到了A鎖'%self.name)mutexB.acquire()print('%s獲取到了B鎖'%self.name)mutexB.release()mutexA.release()if __name__ == '__main__':#線程切換的速度非常快,因此可以看成是依次線程執行的for i in range(10):t = mythread()t.start()
?
2.遞歸鎖(RLock):可以解決死鎖的問題
知識點:RLock(),
1)支持被同一個線程連續多次被獲取(acquire),
2)內置一個計數器,同一線程每acquire一次,計數器+1,每release·一次,計數器-1,一直到計數器歸零,這把遞歸鎖才能被其他線程獲取(acquire)
#遞歸鎖情況
from threading import Thread,RLock
import time
#設置了兩把互斥鎖
mutexA = mutexB = RLock()class mythread(Thread):def run(self):self.f1()self.f2()def f1(self):#首先線程1獲得了A鎖計數器+1為1,再獲得B鎖計數器+1為2,最后兩個都釋放計數器歸零,鎖可以被其他線程獲取,因為線程速度快,所以線程1獲取到了f2的B鎖,計數器為1,因為沉睡了0.1秒且線程1的計數器為1,雖然足以讓線程2去獲得f1中的A鎖,但是條件不允許啊(計數器不歸零),接下來線程1的工作是沉睡結束后獲得A鎖,計數器為2,線程1釋放兩次后計數器為0,線程2立馬獲得鎖,不一定是線程2獲得mutexA.acquire()print('%s獲取到了A鎖'%self.name)mutexB.acquire()print('%s獲取到了B鎖'%self.name)mutexB.release()mutexA.release()def f2(self):mutexB.acquire()print('%s獲取到了B鎖'%self.name)time.sleep(0.1)mutexA.acquire()print('%s獲取到了A鎖'%self.name)mutexA.release()mutexB.release()if __name__ == '__main__':#線程切換的速度非常快,因此可以看成是依次線程執行的for i in range(10):t = mythread()t.start()
#運行結果
'''
"F:\software install\python3.6.4\python.exe" C:/Users/jinlin/Desktop/python_further_study/并發編程/死鎖與遞歸鎖(Rlock).py
Thread-1獲取到了A鎖
Thread-1獲取到了B鎖
Thread-1獲取到了B鎖
Thread-1獲取到了A鎖
Thread-2獲取到了A鎖
Thread-2獲取到了B鎖
Thread-2獲取到了B鎖
Thread-2獲取到了A鎖
Thread-4獲取到了A鎖
Thread-4獲取到了B鎖
Thread-4獲取到了B鎖
Thread-4獲取到了A鎖
Thread-6獲取到了A鎖
Thread-6獲取到了B鎖
Thread-6獲取到了B鎖
Thread-6獲取到了A鎖
Thread-8獲取到了A鎖
Thread-8獲取到了B鎖
Thread-8獲取到了B鎖
Thread-8獲取到了A鎖
Thread-10獲取到了A鎖
Thread-10獲取到了B鎖
Thread-10獲取到了B鎖
Thread-10獲取到了A鎖
Thread-5獲取到了A鎖
Thread-5獲取到了B鎖
Thread-5獲取到了B鎖
Thread-5獲取到了A鎖
Thread-9獲取到了A鎖
Thread-9獲取到了B鎖
Thread-9獲取到了B鎖
Thread-9獲取到了A鎖
Thread-7獲取到了A鎖
Thread-7獲取到了B鎖
Thread-7獲取到了B鎖
Thread-7獲取到了A鎖
Thread-3獲取到了A鎖
Thread-3獲取到了B鎖
Thread-3獲取到了B鎖
Thread-3獲取到了A鎖進程已結束,退出代碼0
'''
?