互斥鎖引入背景:
# -*- coding=utf-8 -*-
# author: bolin chen
# @date : 2021-02-22
import threading, time
num = 0
def th1(temp):
global num
for i in range(temp):
num += 1
print(f"----------in the th1 num is : ----------")
def th2(temp):
global num
for i in range(temp):
num += 1
print(f"----------in the th2 num is : ----------")
def main():
t1 = threading.thread(target=th1, args=(1000000,))
t2 = threading.thread(target=th2, args=(1000000,))
t1.start()
# time.sleep(1)
t2.start()
time.sleep(3)
print(f"------- ---in the main num is : ----------")
if __name__ == '__main__':
main()
執行結果如下:
----------in the th1 num is : 1165597----------
----------in the th2 num is : 1262044----------
------- ---in the main num is : 1262044----------
經過分析發下,當使用兩個執行緒對全域性變數(初始值為0)各進行100萬次的 +1 操作,最終結果卻不是 200萬,但是把增加的次數變為 10、100、1000、10000、10000,結果都是和預期符合的20、200、2000、20000、200000,這裡其實就是cpu在呼叫多執行緒的邏輯,每次呼叫單個執行緒,並不是一定把單個執行緒的這段**執行完畢才切換到另乙個執行緒,可能這一段**執行到一半就切換到另乙個執行緒去了,導致兩個執行緒 +1 的操作都是基於某個數字+1,但是當前面執行到一半的執行緒切換回來執行完後,此時的數字已經+1,但是後面的執行緒的後一半**還是基於之前的數字,所以這次 +1 的操作就沒有實際意義,導致兩次+1原先應該+2 的操作就只出現了+1;
那麼怎樣可以解決上面的問題?
如果我們控制某個執行緒在執行對全域性資料修改時的操作不進行切換,修改完後再切換到另乙個執行緒不就可以了嗎?所以這時候就出現了互斥鎖。
互斥鎖作用:
某個執行緒要更改共享資料時,先將其鎖定,此時資源的狀態為「鎖定」,其他執行緒不能更改;直到該執行緒釋放資源,將資源的狀態變成「非鎖定」,其他的執行緒才能再次鎖定該資源。互斥鎖保證了每次只有乙個執行緒進行寫入操作,從而保證了多執行緒情況下資料的正確性。
怎麼使用互斥鎖呢?
threading 模組中定義了 lock 類,可以方便處理鎖定;
# 建立鎖
mutex = threading.lock()
# 鎖定
mutex.acquire()
# 釋放
mutex.release()
注意
import threading, time
# 使用互斥鎖完成2個執行緒對同乙個全域性變數各加100萬次的操作
num = 0
mutex = threading.lock() # 建立乙個互斥鎖
def th1(temp):
global num
mutex.acquire()
for i in range(temp):
num += 1
mutex.release()
print(f"----------in the th1 num is : ----------")
def th2(temp):
global num
mutex.acquire()
for i in range(temp):
num += 1
mutex.release()
print(f"----------in the th2 num is : ----------")
def main():
t1 = threading.thread(target=th1, args=(1000000,))
t2 = threading.thread(target=th2, args=(1000000,))
t1.start()
# time.sleep(1)
t2.start()
# time.sleep(3)
print(f"----------in the main num is : ----------")
if __name__ == '__main__':
main()
執行結果如下:
----------in the main num is : 260187----------
----------in the th1 num is : 1000000----------
----------in the th2 num is : 2000000----------
這裡可以看到,如果互斥鎖加在 for 迴圈外面,那麼一定會等到乙個執行緒執行完 for 迴圈才會切換到另乙個執行緒,所以第乙個 num 列印的值一定是 1000000;
嘗試變更互斥鎖的位置:
num = 0
mutex = threading.lock() # 建立乙個互斥鎖
def th1(temp):
global num
for i in range(temp):
mutex.acquire()
num += 1
mutex.release()
print(f"----------in the th1 num is : ----------")
def th2(temp):
global num
for i in range(temp):
mutex.acquire()
num += 1
mutex.release()
print(f"----------in the th2 num is : ----------")
def main():
t1 = threading.thread(target=th1, args=(1000000,))
t2 = threading.thread(target=th2, args=(1000000,))
t1.start()
# time.sleep(1)
t2.start()
# time.sleep(3)
print(f"----------in the main num is : ----------")
if __name__ == '__main__':
main()
執行結果如下:
----------in the main num is : 44445----------
----------in the th1 num is : 1936222----------
----------in the th2 num is : 2000000----------
這時可以看出,th1 中的 num 其實是在第乙個執行緒執行 for 迴圈時候,兩個執行緒對 num 共同+1 的結果,最後的 num 結果則是後執行完的執行緒最後一次 +1 的操作的結果,由於**中加了互斥鎖,每次每個執行緒對 num 變數進行操作都是有意義的,最終 num 被操作200萬次; python執行緒互斥鎖 Python多執行緒與互斥鎖
多執行緒 threading python的thread模組是 較底層的模組,python的threading 模組是對thread做了 些包裝的,可以更加 便的被使 1.使 threading模組 from threading import thread 匯入模組 t thread target ...
簡述python多執行緒中的互斥鎖
在程式設計 中,為了 保證共享資料 操作的完整性,引入了 互斥鎖的概念。每個 物件都對應於乙個可稱為 互斥鎖 的標記,這個標記用來保證在任一時刻,只能有乙個 執行緒訪問該 物件。在python中由於多執行緒的存在,並且對全域性變數作用時有可能產生全域性變數紊亂問題,所以也加入了同步和互斥等方法,但是...
多執行緒中的互斥鎖
互斥量mutex 類物件,理解成一把鎖,多個執行緒嘗試用lock 成員函式來對其加鎖,只有乙個執行緒能夠鎖定成功 lock 與unlock 須成對存在,很容易出問題,所以引入 std lock guard 類模板,對於忘記新增unlock 會自動新增,類似於智慧型指標的功能。鎖住的 量多少成為粒度的...