進擊のpython
並發編程——死鎖和遞歸鎖
死鎖是一種現象:
兩個及以上的進程或者線程在爭搶資源的過程中,出現的互相等待的現象
如果沒有外部干預,他們就一直僵持,永遠在互相等待,就“死”住了
看一下現象:
from threading import Thread, Lock
def func(A, B):
A.acquire()
print('A:這是func函數的開始.. ..')
B.acquire()
print('B:這是func函數的開始.. ..')
B.release()
print('B:這是func函數的結束!')
A.release()
print('A:這是func函數的結束!')
def inner(A, B):
B.acquire()
print('A:這是inner函數的開始.. ..')
A.acquire()
print('B:這是inner函數的開始.. ..')
A.release()
print('B:這是inner函數的結束!')
B.release()
print('A:這是inner函數的結束!')
def main(A, B):
func(A, B)
inner(A, B)
if __name__ == '__main__':
A = Lock()
B = Lock()
for i in range(10):
t = Thread(target=main, args=(A, B))
t.start()
執行的時候就會出現阻塞情況(自己執行)
那我也想保護func里面的數據,也想保護inner里面的數據,應該怎么辦?
遞歸鎖
為了解決上述問題,遞歸鎖應運而生
為了支持在同一線程中多次請求同一資源,python就提供了重入鎖RLock
這個鎖就很有意思,他里面除了互斥鎖Lock以外,還有一個計數器counter
counter記錄了acquire的次數,從而使得資源可以被多次require
直到一個線程所有的acquire都被release,其他的線程才能獲得資源
上面的例子如果使用RLock代替Lock,則不會發生死鎖
二者的區別是:遞歸鎖可以連續acquire多次,而互斥鎖只能acquire一次
from threading import Thread, RLock
def func(A, B):
A.acquire()
print('A:這是func函數的開始.. ..')
B.acquire()
print('B:這是func函數的開始.. ..')
B.release()
print('B:這是func函數的結束!')
A.release()
print('A:這是func函數的結束!')
def inner(A, B):
B.acquire()
print('B:這是inner函數的開始.. ..')
A.acquire()
print('A:這是inner函數的開始.. ..')
A.release()
print('A:這是inner函數的結束!')
B.release()
print('B:這是inner函數的結束!')
def main(A, B):
func(A, B)
inner(A, B)
if __name__ == '__main__':
B = A = RLock() # 區別在這!
for i in range(10):
t = Thread(target=main, args=(A, B))
t.start()