1. 程式人生 > 程式設計 >Python 多執行緒共享變數的實現示例

Python 多執行緒共享變數的實現示例

多執行緒-共享全域性變數

#coding=utf-8
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_num
 print("----in work2,g_num is %d---"%g_num)


print("---執行緒建立之前g_num is %d---"%g_num)

t1 = Thread(target=work1)
t1.start()

#延時一會,保證t1執行緒中的事情做完
time.sleep(1)

t2 = Thread(target=work2)
t2.start()

執行如下:

[root@server01 many_task]# python test5.py
---執行緒建立之前g_num is 100---
----in work1,g_num is 103---
----in work2,g_num is 103---
[root@server01 many_task]#

從上面兩個執行緒執行的結果來看,執行緒t1將 g_num 加到 103,線上程t2也是列印g_num=103。所以對於兩個執行緒,g_num這個全域性變數是共享的。

列表當做實參傳遞到執行緒中

#coding=utf-8
from threading import Thread
import time

def work1(nums):
 nums.append(44)
 print("----in work1---",nums)

def work2(nums):
 #延時一會,保證t1執行緒中的事情做完
 time.sleep(1)
 print("----in work2---",nums)

g_nums = [11,22,33]

t1 = Thread(target=work1,args=(g_nums,))
t1.start()

t2 = Thread(target=work2,))
t2.start()

執行如下:

[root@server01 many_task]# python test6.py
('----in work1---',[11,33,44])
('----in work2---',44])

總結:
在一個程序內的所有執行緒共享全域性變數,很方便在多個執行緒間共享資料
缺點就是,執行緒是對全域性變數隨意遂改可能造成多執行緒之間對全域性變數的混亂(即執行緒非安全)

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

多執行緒開發可能遇到的問題

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

編寫程式碼測試如下:

[root@server01 many_task]# vim test4.py 

#coding=utf-8
import threading
from time import sleep,ctime

# 初始化g_num
g_num = 0

def add_func1(num):
 global g_num
 for i in range(num):
  g_num += 1
  print("add_func1,第%d次,g_num等於%d" % (i,g_num))
  #sleep(0.5)

def add_func2(num):
 global g_num
 for i in range(num):
  g_num += 1
  print("add_func2,第%d次,g_num等於%d" % (i,g_num))
  #sleep(0.5)

def main():
 # 執行執行緒
 t1 = threading.Thread(target=add_func1,args=(100,))
 t2 = threading.Thread(target=add_func2,))

 t1.start()
 t2.start()

 # 判斷當執行緒存在,則等待1秒
 while len(threading.enumerate()) > 1:
  sleep(1)

 print("2個執行緒對同一個全域性變數操作之後的最終結果是:%s" % g_num)

if __name__ == '__main__':
 main()

執行如下:

add_func2,第96次,g_num等於197
add_func2,第97次,g_num等於198
add_func2,第98次,g_num等於199
add_func2,第99次,g_num等於200
2個執行緒對同一個全域性變數操作之後的最終結果是:200
[root@server01 many_task]#

兩個執行緒雖然執行很快,但是g_num恰好就是100+100=200的結果,是正確的。不過,這個數量少,可能看不出問題來。

測試示例2

[root@server01 many_task]# vim test7.py 

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=(10000000,))
t1.start()

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

while len(threading.enumerate()) != 1:
 time.sleep(1)

print("2個執行緒對同一個全域性變數操作之後的最終結果是:%s" % g_num)

執行如下:

[root@server01 many_task]# python test7.py
---執行緒建立之前g_num is 0---
----in work1,g_num is 11977799---
----in work2,g_num is 19108796---
2個執行緒對同一個全域性變數操作之後的最終結果是:19108796
[root@server01 many_task]#

正確的結果應該是:20000000

結論

如果多個執行緒同時對同一個全域性變數操作,會出現資源競爭問題,從而資料結果會不正確

到此這篇關於Python 多執行緒共享變數的實現示例的文章就介紹到這了,更多相關Python 多執行緒共享變數內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!