在程式設計
中,為了
保證共享資料
操作的完整性,引入了
互斥鎖的概念。每個
物件都對應於乙個可稱為" 互斥鎖" 的標記,這個標記用來保證在任一時刻,只能有乙個
執行緒訪問該
物件。在python中由於多執行緒的存在,並且對全域性變數作用時有可能產生全域性變數紊亂問題,所以也加入了同步和互斥等方法,但是我們主要講解互斥鎖:
如下**定義了乙個my_num的全域性變數,而函式sum1和函式sum2都執行對my_num加1操作,並且都執行100萬次+1,在下面的**裡,我們建立了兩個分別執行兩個函式的執行緒,然後呼叫start()啟動執行緒
importthreading得到執行結果如下:importtime
# 定義全域性變數
my_num = 0
# 迴圈給全域性變數每次加上1
defsum1():
globalmy_num
foriinrange(1000000):
my_num += 1
print("sum1:"
, my_num)
# 迴圈給全域性變數每次加上1
defsum2():
globalmy_num
foriinrange(1000000):
my_num += 1
print("sum2:"
, my_num)
if__name__ == '__main__':
# 建立兩個子執行緒
first_thread = threading.thread(target=sum1)
second_thread = threading.thread(target=sum2)
# 啟動執行緒執行對應的任務
first_thread.start()# 主線程延時1.5秒
# time.sleep(1.5)
# 主線程等待第乙個執行緒執行完成以後,**再繼續往下執行,啟動第二個執行緒執行任務
# first_thread.join() # 執行緒同步: 按照預先定義好的順序乙個任務執行完成另外乙個任務再執行
# print("第乙個執行緒執行完了")
second_thread.start()
sum1: 1239023顯然這結果不是我們想要的,我們希望的結果是函式1和函式2都執行100萬次加一,最終結果是想變成200萬,當然,出現這樣的結果,我們也很容易想到原因是:當全域性變數my_num 剛好等於1000(某些數字時,這裡只是假設)的時候,兩個執行緒同時拿到了my_num的值,各自對他進行了+1操作,此時明顯全域性my_num的到的只是加一而不是+2操作(不往細了說)sum2: 1341576
明顯看出:在乙個程序內非常方便多個執行緒對全域性變數的資料共享,而對全域性變數進行隨意修改可能會造成全域性變數的混亂,即多個執行緒同時對乙個全域性變數操作,會出現資源競爭問題,從而資料結果不正確。
同樣,下面的**中我們加入了互斥鎖
互斥鎖為資源引入乙個狀態:鎖定/非鎖定
某個執行緒要更改共享資料時,先將其鎖定,此時資源的狀態為「鎖定」,其他執行緒不能更改;直到該執行緒釋放資源,將資源的狀態變成「非鎖定」,其他的執行緒才能再次鎖定該資源。互斥鎖保證了每次只有乙個執行緒進行寫入操作,從而保證了多執行緒情況下資料的正確性。
當乙個執行緒呼叫鎖的acquire()方法獲得鎖時,鎖就進入「locked」狀態。
每次只有乙個執行緒可以獲得鎖。如果此時另乙個執行緒試圖獲得這個鎖,該執行緒就會變為「blocked」狀態,稱為「阻塞」,直到擁有鎖的執行緒呼叫鎖的release()方法釋放鎖之後,鎖進入「unlocked」狀態。
執行緒排程程式從處於同步阻塞狀態的執行緒中選擇乙個來獲得鎖,並使得該執行緒進入執行(running)狀態。
importthreading可以看到最後的結果,加入互斥鎖後,其結果與預期相符。# 定義全域性變數
my_num = 0
# 建立互斥鎖
lock = threading.lock()
# def show():
# print("哈哈")
# # 變數儲存的是函式在記憶體中的位址,儲存的函式引用
# a = show
# a()
# 迴圈給全域性變數每次加上1
defsum1():
# 上鎖
lock.acquire()
globalmy_num
foriinrange(1000000):
my_num += 1
print("sum1:"
, my_num)
# 釋放鎖
lock.release()
# 迴圈給全域性變數每次加上1
defsum2():
# 上鎖
lock.acquire()
globalmy_num
foriinrange(1000000):
my_num += 1
print("sum2:"
, my_num)
# 釋放鎖
lock.release()
if__name__ == '__main__':
# 建立兩個子執行緒
first_thread = threading.thread(target=sum1)
second_thread = threading.thread(target=sum2)
# 啟動執行緒執行對應的任務
first_thread.start()
second_thread.start()
# 互斥鎖:能保證統一時刻只有乙個執行緒執行,那個執行緒搶到這個互斥鎖我們決定不了,但是能保證資料最終不會有問題
得到結果:
sum1: 1000000鎖的好處:sum2: 2000000
鎖的壞處:
python執行緒互斥鎖 Python多執行緒與互斥鎖
多執行緒 threading python的thread模組是 較底層的模組,python的threading 模組是對thread做了 些包裝的,可以更加 便的被使 1.使 threading模組 from threading import thread 匯入模組 t thread target ...
多執行緒中的互斥鎖
互斥量mutex 類物件,理解成一把鎖,多個執行緒嘗試用lock 成員函式來對其加鎖,只有乙個執行緒能夠鎖定成功 lock 與unlock 須成對存在,很容易出問題,所以引入 std lock guard 類模板,對於忘記新增unlock 會自動新增,類似於智慧型指標的功能。鎖住的 量多少成為粒度的...
Linux 多執行緒互斥量互斥
同乙個程序中的多個執行緒共享所在程序的記憶體資源,當多個執行緒在同一時刻同時訪問同一種共享資源時,需要相互協調,以避免出現資料的不一致和覆蓋等問題,執行緒之間的協調和通訊的就叫做執行緒的同步問題,執行緒同步的思路 讓多個執行緒依次訪問共享資源,而不是並行 mutex被建立時可以有初始值,表示mute...