day 0807 多執行緒 共享全域性變數問題

2021-09-25 23:58:39 字數 3482 閱讀 5073

假設有兩個執行緒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 ...