Python 中多線程共享全局變量的問題


在之前,我們講過了,Python 中多個線程之間是可以共享全局變量的數據的。

但是,多線程共享全局變量是會出問題的。

假設兩個線程 t1 和 t2 都要對全局變量 g_num (默認是0)進行加1運算,t1 和 t2 都各對 g_num 加10次,g_num 的最終的結果應該為20。

但是由於多線程是同時操作,有可能出現下面情況:

在 g_num=0 時,t1 取得 g_num=0。此時系統把 t1 調度為”sleeping”狀態,把t2轉換為”running”狀態,t2 也獲得 g_num=0。

然后 t2 對得到的值進行加1並賦給 g_num,使得 g_num=1 。

接着系統又把 t2 調度為”sleeping”,把 t1 轉為”running”。線程t1又把它之前得到的0加1后賦值給g_num。

這樣導致雖然 t1 和 t2 都對 g_num 加1,但結果仍然是 g_num=1。

先看例子:

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 is %d---" % g_num)

t1 = threading.Thread(target=work1, args=(100,))
t1.start()

t2 = threading.Thread(target=work2, args=(100,))
t2.start()

# 確保子線程都運行結束
while len(threading.enumerate()) != 1:
    time.sleep(1)

print("2個線程對同一個全局變量操作之后的最終結果是:%s" % g_num)

運行結果:

---線程創建之前g_num is 0---
----in work1, g_num is 100---
----in work2, g_num is 200---
2個線程對同一個全局變量操作之后的最終結果是:200

乍一看,好像沒出什么問題。那是因為數據太小了,我們現在把數據變大。

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 is %d---" % g_num)

t1 = threading.Thread(target=work1, args=(1000000,))
t1.start()

t2 = threading.Thread(target=work2, args=(1000000,))
t2.start()

# 確保子線程都運行結束
while len(threading.enumerate()) != 1:
    time.sleep(1)

print("2個線程對同一個全局變量操作之后的最終結果是:%s" % g_num)

運行結果:

---線程創建之前g_num is 0---
----in work2, g_num is 1048576---
----in work1, g_num is 1155200---
2個線程對同一個全局變量操作之后的最終結果是:1155200

數越大,出現問題的概率越大,而且數據的偏差也越大。

結論

如果多個線程同時對同一個全局變量操作,會出現資源競爭問題,從而數據結果會不正確。

那能不能解決這個問題呢?

我們后面會講同步和互斥鎖的問題的。

通過同步和互斥鎖,我們可以解決 Python 中多線程共享全局變量時發生錯誤的問題。


編程的朝聖之路


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM