假設有兩個執行緒t1,t2假設都要對乙個全域性變數g_num進行運算,兩個執行緒t1和t2分別對g_num各加10次,g_num的最終結果
import threading
import time
g_num=0
def work1(num):
global g_num
for i in range(num):
g_num+=1
print('---in work1,g_num is %d---'% g_num)
def work2(num):
global g_num
for i in range(num):
g_num+=1
print('---in work2,g_num is %d---'% g_num)
print('----執行緒建立之前g_num:%d'% g_num)
t1=threading.thread(target=work1,args=(10,))
t2=threading.thread(target=work2,args=(10,))
t1.start()
t2.start()
while len(threading.enumerate()) !=1:
time.sleep(1)
print('2個執行緒對同乙個變數的最終結果:',g_num)
----執行緒建立之前g_num:0
—in work1,g_num is 10—
—in work2,g_num is 20—
2個執行緒對同乙個變數的最終結果: 20
在num=0時,t1取得num=0,此時系統把t1排程為『sleeping』的狀態,t2準換為『running』的狀態,t2也獲得num=0。然後,t2對得到的值進行加1並賦給num。num=1,然後系統又將t2排程為『sleeping』的狀態,把t1轉換為『running『,執行緒t1又把它之前得到的0加1後賦值給num.這種情況,明明倆執行緒都完成了乙個次工作,但結果還是num=1
因為電腦執行速度過快,t2還來不及與t1進行執行緒切換,t1就執行完了,如果將10改為1000000,會發現
----執行緒建立之前g_num:0
—in work1,g_num is 1144345—
—in work2,g_num is 1195423—
2個執行緒對同乙個變數的最終結果: 1195423
兩條執行緒由於共享資源,會對資源產生競爭,導致資料結果不正確
同步,就是協同步調,按照預定的先後次序進行執行。好比說相聲,乙個說完,另外乙個人再說。
程序和執行緒同步,可以理解為程序或者執行緒a和b一塊配黑,a執行一定程度時需要依賴b的某個結果,於是停下來,讓b執行,b開始執行,再將結果給a,a再繼續操作,如此往復,直至程式結束。
通過』執行緒同步』來進行解決
思路:當多個執行緒幾乎同時修改某個共享資料時,需要進行同步控制。
執行緒同步能夠保證多個執行緒安全訪問競爭資源,最簡單的同步機制就是引入互斥鎖。
互斥鎖為我們的資源引入乙個狀態: 鎖定/非鎖定
某個執行緒要更改共享資料時,先將其鎖定,此時資源狀態為鎖定,其他執行緒不能對其更改;直到該執行緒釋放資源,資源狀態變為』非鎖定『狀態,其他執行緒才能再次鎖定該資源。
互斥鎖,保證了每次只有乙個執行緒進行寫入操作,從而保證了多執行緒情況下資料的正確性。
在threading模組裡,定義了lock()類,可以方便的處理鎖定。
mutex = threading.lock(
)#建立
mutex.acquire(
[blocking]
)#鎖定
mutex.release(
)#釋放
import threading
import time
g_num=0
def work1(num):
global g_num
for i in range(num):
if mutex.acquire(true):
g_num+=1
mutex.release()
print('---in work1,g_num is %d---'% g_num)
def work2(num):
global g_num
for i in range(num):
if mutex.acquire(true):
g_num += 1
mutex.release()
print('---in work2,g_num is %d---'% g_num)
print('----執行緒建立之前g_num:%d'% g_num)
mutex=threading.lock()
t1=threading.thread(target=work1,args=(1000000,))
t2=threading.thread(target=work2,args=(1000000,))
t1.start()
t2.start()
while len(threading.enumerate()) !=1:
time.sleep(1)
print('2個執行緒對同乙個變數的最終結果:',g_num)
----執行緒建立之前g_num:0
—in work1,g_num is 1917539—
—in work2,g_num is 2000000—
2個執行緒對同乙個變數的最終結果: 2000000
死鎖一般很少發生,但一旦發生就會造成應用停止響應。
也就是有限緩衝問題,是乙個多執行緒同步的經典案例
描述乙個兩個固定大小緩衝區的執行緒-即所謂的「生產者」和消費者 在實際執行時會發生的問題。
生產者的主要作用,生成一定量的資料放在緩衝區中,然後,重複此過程。與此同時,消費者也在緩衝區消耗這些資料
整個問題的關鍵是,生產者不會在緩衝區滿時加入資料,消費者也不會在緩衝區空時消耗資料。
解決辦法
要解決該問題,就必須讓生產者在緩衝區滿時休眠(要麼乾脆就放棄資料),等到下次消費者消耗緩衝區中的資料的時候,生產者才能被喚醒,開始往緩衝區新增資料。同樣,也可以讓消費者在緩衝區空時進入休眠,等到生產者往緩衝區新增資料之後,再喚醒消費者。通常採用程序間通訊的方法解決該問題,常用的方法有訊號燈法等。如果解決方法不夠完善,則容易出現死鎖的情況。出現死鎖時,兩個執行緒都會陷入休眠,等待對方喚醒自己。該問題也能被推廣到多個生產者和消費者的情形
1.佇列,先進先出
2.棧,先進後出
python中queue(py3)(py2,queue),模組提供了乙個同步的,執行緒安全的佇列類,包括先入先出(fifo)佇列queue,和**先出(lifo)佇列lifoqueue和優先順序佇列priorityqueue.
可以使用佇列來實現執行緒間的同步
fifo佇列實現生產者消費者問題
多執行緒共享變數 多執行緒共享全域性變數
1.多執行緒的執行順序是無序的 像2個人賽跑,乙個先跑乙個後跑,但根據每個人跑的速度不一樣,跑一半,二者可能跑在一起去了。2.又因為多執行緒是共享乙個全域性變數的,就導致資料容易被弄髒 假如老闆讓兩個員工寫兩個主題ppt,若這兩個人沒商量好,都做了同乙個主題的ppt,導致不但速度很慢,且這個ppt有...
多執行緒 共享全域性變數問題
多執行緒 共享全域性變數問題 多執行緒開發可能遇到的問題 假設兩個執行緒t1和t2都要對全域性變數g num 預設是0 進行加1運算,t1和t2都各對g num加10次,g num的最終的結果應該為20。但是由於是多執行緒同時操作,有可能出現下面情況 在g num 0時,t1取得g num 0。此時...
python多執行緒 共享全域性變數
from threading import thread import time g num 100 def work1 global g num for i in range 3 g num 1 print in work1,g num is d g num def work2 global g ...