python多線程互斥鎖與死鎖
一、多線程間的資源競爭
以下列task1()
,task2()
兩個函數為例,分別將對全局變量num加一重復一千萬次循環(數據大一些,太小的話執行太快,達不到驗證的效果)。
import threading import time num = 0 def task1(nums): global num for i in range(nums): num += 1 print("task1---num=%d" % num) def task2(nums): global num for i in range(nums): num += 1 print("task2---num=%d" % num) if __name__ == '__main__': nums = 10000000 t1 = threading.Thread(target=task1, args=(nums,)) t2 = threading.Thread(target=task2, args=(nums,)) t1.start() t2.start() # 因為主線程不會等子線程執行完就會執行,所以這裡延遲五秒,確保最後執行。 time.sleep(5) print("main----num=%d" % num)
程序運行結果:
如圖,輸出結果比較混亂,既沒有一千萬,最終結果也不是二千萬。因為多線程運行時出現瞭資源競爭,即可以理解為,每個函數運行的時間都不確定,且互相影響,
如從初始值0開始,假設t1的線程先執行,執行到+1後,此時的num=1還未存儲,然後即被叫停,t2開始執行,去獲取num,獲取到的num等於初始值0,然後其執行瞭+1並存儲,存儲後num=1,然後t2停止t1繼續,再次存儲num=1。即加瞭兩次1,但是num還是隻等於1。
因為t1和t2誰來運行的分配是完全隨機的,所以最後加瞭兩千萬次1後值是小於2000萬的。
解決此類問題,可以使用到互斥鎖 。
二、互斥鎖
- 某個線程要更改共享數據時,先將其鎖定,此時資源的狀態為"鎖定",其他線程不能改變,隻到該線程釋放資源,將資源的狀態變成"非鎖定",其他的線程才能再次鎖定該資源。
- 互斥鎖保證瞭每次隻有一個線程進行寫入操作,從而保證瞭多線程情況下數據的正確性。
1.互斥鎖示例
創建一把鎖:
mutex = threading.Lock()
mutex.acquire() # 上鎖 xxxx鎖定的內容xxxxx mutex.release() # 解鎖
將互斥鎖加入到上邊的代碼中如下,則問題得到瞭解決。
import threading import time num = 0 def task1(nums): global num mutex.acquire() for i in range(nums): num += 1 mutex.release() print("task1---num=%d" % num) def task2(nums): global num mutex.acquire() for i in range(nums): num += 1 mutex.release() print("task2---num=%d" % num) if __name__ == '__main__': nums = 10000000 mutex = threading.Lock() t1 = threading.Thread(target=task1, args=(nums,)) t2 = threading.Thread(target=task2, args=(nums,)) t1.start() t2.start() # 因為主線程不會等子線程執行完就會執行,所以這裡延遲五秒,確保最後執行。 time.sleep(5) print("main----num=%d" % num)
程序運行結果:
2.可重入鎖與不可重入鎖
threading.Lock()
上的是不可重入鎖,即一次隻能加一把鎖,不能加多把。
threading.Lock()
如果需要同時加多把所,則需加入不可重入鎖
創建一把可重入鎖:
mutex = threading.RLock() mutex.acquire() # 上鎖 mutex.acquire() # 再上鎖 xxxx鎖定的內容xxxxx mutex.release() # 解鎖 mutex.release() # 再解鎖
其中上鎖和解鎖的次數必須保持一致。
三、死鎖
在線程間共享多個資源的時候,如果兩個線程分別占有一部分資源並且同時等待對方的資源,就會程序堵塞,造成死鎖。
- 死鎖一般用不到。
- 程序設計要盡量避免。
到此這篇關於python多線程互斥鎖與死鎖的文章就介紹到這瞭,更多相關python多線程互斥鎖與死鎖內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!