python多線程互斥鎖與死鎖
一、多線程間的資源競爭
以下列task1()
,task2()
兩個函數(shù)為例,分別將對全局變量num加一重復一千萬次循環(huán)(數(shù)據(jù)大一些,太小的話執(zhí)行太快,達不到驗證的效果)。
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() ? ? # 因為主線程不會等子線程執(zhí)行完就會執(zhí)行,所以這里延遲五秒,確保最后執(zhí)行。 ? ? time.sleep(5) ? ? print("main----num=%d" % num)
程序運行結(jié)果:
如圖,輸出結(jié)果比較混亂,既沒有一千萬,最終結(jié)果也不是二千萬。因為多線程運行時出現(xiàn)了資源競爭,即可以理解為,每個函數(shù)運行的時間都不確定,且互相影響,
如從初始值0開始,假設(shè)t1的線程先執(zhí)行,執(zhí)行到+1后,此時的num=1還未存儲,然后即被叫停,t2開始執(zhí)行,去獲取num,獲取到的num等于初始值0,然后其執(zhí)行了+1并存儲,存儲后num=1,然后t2停止t1繼續(xù),再次存儲num=1。即加了兩次1,但是num還是只等于1。
因為t1和t2誰來運行的分配是完全隨機的,所以最后加了兩千萬次1后值是小于2000萬的。
解決此類問題,可以使用到互斥鎖 。
二、互斥鎖
- 某個線程要更改共享數(shù)據(jù)時,先將其鎖定,此時資源的狀態(tài)為"鎖定",其他線程不能改變,只到該線程釋放資源,將資源的狀態(tài)變成"非鎖定",其他的線程才能再次鎖定該資源。
- 互斥鎖保證了每次只有一個線程進行寫入操作,從而保證了多線程情況下數(shù)據(jù)的正確性。
1.互斥鎖示例
創(chuàng)建一把鎖:
mutex = threading.Lock()
mutex.acquire() # 上鎖 xxxx鎖定的內(nèi)容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() ? ? # 因為主線程不會等子線程執(zhí)行完就會執(zhí)行,所以這里延遲五秒,確保最后執(zhí)行。 ? ? time.sleep(5) ? ? print("main----num=%d" % num)
程序運行結(jié)果:
2.可重入鎖與不可重入鎖
threading.Lock()
上的是不可重入鎖,即一次只能加一把鎖,不能加多把。
threading.Lock()
如果需要同時加多把所,則需加入不可重入鎖
創(chuàng)建一把可重入鎖:
mutex = threading.RLock() mutex.acquire() # 上鎖 mutex.acquire() # 再上鎖 xxxx鎖定的內(nèi)容xxxxx mutex.release() # 解鎖 mutex.release() # 再解鎖
其中上鎖和解鎖的次數(shù)必須保持一致。
三、死鎖
在線程間共享多個資源的時候,如果兩個線程分別占有一部分資源并且同時等待對方的資源,就會程序堵塞,造成死鎖。
- 死鎖一般用不到。
- 程序設(shè)計要盡量避免。
到此這篇關(guān)于python多線程互斥鎖與死鎖的文章就介紹到這了,更多相關(guān)python多線程互斥鎖與死鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python深度學習pytorch實現(xiàn)圖像分類數(shù)據(jù)集
這篇文章主要為大家講解了關(guān)于Python深度學習中pytorch實現(xiàn)圖像分類數(shù)據(jù)集的示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10Python實現(xiàn)簡易過濾刪除數(shù)字的方法小結(jié)
這篇文章主要介紹了Python實現(xiàn)簡易過濾刪除數(shù)字的方法,結(jié)合實例形式總結(jié)分析了Python基于正則及內(nèi)置函數(shù)過濾刪除數(shù)字的相關(guān)操作技巧,需要的朋友可以參考下2019-01-01python實現(xiàn)多人聊天服務(wù)器以及客戶端
這篇文章主要為大家詳細介紹了python實現(xiàn)多人聊天服務(wù)器以及客戶端,帶圖形化界面,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07python正則表達式re.sub各個參數(shù)的超詳細講解
Python 的 re 模塊提供了re.sub用于替換字符串中的匹配項,下面這篇文章主要給大家介紹了關(guān)于python正則表達式re.sub各個參數(shù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-07-07Python實現(xiàn)登錄人人網(wǎng)并抓取新鮮事的方法
這篇文章主要介紹了Python實現(xiàn)登錄人人網(wǎng)并抓取新鮮事的方法,可實現(xiàn)Python模擬登陸并抓取新鮮事的功能,需要的朋友可以參考下2015-05-05