您好,登錄后才能下訂單哦!
小編這次要給大家分享的是如何實(shí)現(xiàn)Python多線程共享變量,文章內(nèi)容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。
多線程-共享全局變量
#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("---線程創(chuàng)建之前g_num is %d---"%g_num) t1 = Thread(target=work1) t1.start() #延時一會,保證t1線程中的事情做完 time.sleep(1) t2 = Thread(target=work2) t2.start()
執(zhí)行如下:
[root@server01 many_task]# python test5.py
---線程創(chuàng)建之前g_num is 100---
----in work1, g_num is 103---
----in work2, g_num is 103---
[root@server01 many_task]#
從上面兩個線程執(zhí)行的結(jié)果來看,線程t1將 g_num 加到 103,在線程t2也是打印g_num=103。所以對于兩個線程,g_num這個全局變量是共享的。
列表當(dāng)做實(shí)參傳遞到線程中
#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, args=(g_nums,)) t2.start()
運(yùn)行如下:
[root@server01 many_task]# python test6.py
('----in work1---', [11, 22, 33, 44])
('----in work2---', [11, 22, 33, 44])
總結(jié):
在一個進(jìn)程內(nèi)的所有線程共享全局變量,很方便在多個線程間共享數(shù)據(jù)
缺點(diǎn)就是,線程是對全局變量隨意遂改可能造成多線程之間對全局變量的混亂(即線程非安全)
多線程-共享全局變量問題
多線程開發(fā)可能遇到的問題
假設(shè)兩個線程t1和t2都要對全局變量g_num(默認(rèn)是0)進(jìn)行加1運(yùn)算,t1和t2都各對g_num加10次,g_num的最終的結(jié)果應(yīng)該為20。
但是由于是多線程同時操作,有可能出現(xiàn)下面情況:
在g_num=0時,t1取得g_num=0。此時系統(tǒng)把t1調(diào)度為”sleeping”狀態(tài),把t2轉(zhuǎn)換為”running”狀態(tài),t2也獲得g_num=0
然后t2對得到的值進(jìn)行加1并賦給g_num,使得g_num=1
然后系統(tǒng)又把t2調(diào)度為”sleeping”,把t1轉(zhuǎn)為”running”。線程t1又把它之前得到的0加1后賦值給g_num。
這樣導(dǎo)致雖然t1和t2都對g_num加1,但結(jié)果仍然是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(): # 執(zhí)行線程 t1 = threading.Thread(target=add_func1,args=(100,)) t2 = threading.Thread(target=add_func2,args=(100,)) t1.start() t2.start() # 判斷當(dāng)線程存在,則等待1秒 while len(threading.enumerate()) > 1: sleep(1) print("2個線程對同一個全局變量操作之后的最終結(jié)果是:%s" % g_num) if __name__ == '__main__': main()
執(zhí)行如下:
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個線程對同一個全局變量操作之后的最終結(jié)果是:200
[root@server01 many_task]#
兩個線程雖然執(zhí)行很快,但是g_num恰好就是100+100=200的結(jié)果,是正確的。不過,這個數(shù)量少,可能看不出問題來。
測試示例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("---線程創(chuàng)建之前g_num is %d---"%g_num) t1 = threading.Thread(target=work1, args=(10000000,)) t1.start() t2 = threading.Thread(target=work2, args=(10000000,)) t2.start() while len(threading.enumerate()) != 1: time.sleep(1) print("2個線程對同一個全局變量操作之后的最終結(jié)果是:%s" % g_num)
運(yùn)行如下:
[root@server01 many_task]# python test7.py
---線程創(chuàng)建之前g_num is 0---
----in work1, g_num is 11977799---
----in work2, g_num is 19108796---
2個線程對同一個全局變量操作之后的最終結(jié)果是:19108796
[root@server01 many_task]#
正確的結(jié)果應(yīng)該是:20000000
結(jié)論
如果多個線程同時對同一個全局變量操作,會出現(xiàn)資源競爭問題,從而數(shù)據(jù)結(jié)果會不正確
看完這篇關(guān)于如何實(shí)現(xiàn)Python多線程共享變量的文章,如果覺得文章內(nèi)容寫得不錯的話,可以把它分享出去給更多人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。