python多進程,多線程之鎖機制 鎖添加的原因: 在多進程/多線程同時進入臨界資源區獲取和操作共有資源時,會出現資源的爭奪而出現混亂。為了避免這種混亂現象,python提出了鎖機制 線程鎖/進程鎖的定義和運用: 創建鎖對象: lock = Lock() 鎖對象一旦創建,就可以隨時被進程或者線程調用 ...
python多進程,多線程之鎖機制
鎖添加的原因:
在多進程/多線程同時進入臨界資源區獲取和操作共有資源時,會出現資源的爭奪而出現混亂。為了避免這種混亂現象,python提出了鎖機制
線程鎖/進程鎖的定義和運用:
創建鎖對象:
lock = Lock()
鎖對象一旦創建,就可以隨時被進程或者線程調用,並且一次創建鎖只有一把,如果多個資源想同時獲取鎖,必須‘排隊’,等上一個進程/線程釋放了鎖才可以請求獲取鎖
上鎖(也叫請求鎖)
lock.acquire()
acquire()是一個阻塞函數。一旦請求獲取鎖成功,就會把下麵將要執行的程式的變數記憶體空間‘鎖住’;而獲取不成功則會一直阻塞在那裡,等待上一個獲得鎖的進程/線程釋放鎖。
解鎖
lock.release()
死鎖:
死鎖的出現有兩種情況
1) 當一個進程或者一個線程一直調用或者占用同一鎖Lock而不釋放資源而導致其他進程/線程無法獲得鎖,就會出現的死鎖狀況,一直阻塞在aquire()處
2) 當有兩個進程同時想獲取兩個鎖的時候(再往上推就是多個進程想獲取多個鎖),由於兩者都是出於競爭關係,誰也不讓誰,誰快誰得手,但電腦中這種競爭關係是很微妙的,時間的差異性很小,於是,就出現了兩者都阻塞在同一個地方,都無法同時獲得兩個鎖或者獲取對方已經獲取的但還沒有釋放的鎖。
為瞭解決死鎖的問題,於是python提出了可重入鎖的機制(RLock)
重入鎖定義後,一個進程就可以重覆調用指定次數的一個重入鎖,而不用去跟別的進程一起爭奪其他鎖。
重入鎖中內部管理者兩個對象,即Lock對象和鎖的調用次數count
下麵說說RLock到底是怎麼用的
1)RLock的定義
mutexA = mutexB = RLock( )
mutex值可以是多個的,定義了多少個,RLock內部的count就為幾
2)RLock的請求
mutexA.acquire()
mutexA.acquire()
每申請一次鎖,count就減1,兩次請求過後,count從2減為0
因為上面定義的重入鎖的內部個數為2,所以該重入鎖可以被一個進程調用兩次,並且在雖然它內部有多個鎖,但只能由一個進程/線程調用,其他進程/線程不能幹預,只有當這個進程/線程釋放掉所有的重入鎖,count=2時才可以被其他進程/線程調用。
3)RLock鎖的釋放
mutexA.release()
mutexB.release()
舉例:
from multiprocessing import RLock,Process from time import ctime,sleep muxteA = mutexB =RLock() def fn1(): muxteA.acquire() sleep(1) print(ctime(),'進程1獲取A鎖') mutexB.acquire() sleep(2) print(ctime(),'進程1獲取B鎖') muxteA.release() print('進程1釋放A鎖') mutexB.release() print('進程1釋放B鎖') def fn2(): muxteA.acquire() sleep(1) print(ctime(),'進程2獲取A鎖') mutexB.acquire() sleep(1) print(ctime(),'進程2獲取B鎖') muxteA.release() print('進程2釋放A鎖') mutexB.release() print('進程2釋放B鎖') p1 = Process(target=fn1) p2 = Process(target=fn2) p1.start() p2.start() p1.join() p2.join()
結果如下:
那麼如果我讓進程2先開啟呢?
結果如下:
顯然,鎖的獲得是誰快誰得手,同時也驗證了我上面描述的,一個進程對一個可重入鎖的請求是排他型的,一旦這個進程請求了一個可重入鎖,那麼其他進程就無法再請求了,直到這個進程釋放了可重入鎖內部的所有鎖。