Python 多線程共享變量的實(shí)現(xiàn)示例
多線程-共享全局變量
#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()
#延時(shí)一會(huì),保證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]#
從上面兩個(gè)線程執(zhí)行的結(jié)果來(lái)看,線程t1將 g_num 加到 103,在線程t2也是打印g_num=103。所以對(duì)于兩個(gè)線程,g_num這個(gè)全局變量是共享的。
列表當(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):
#延時(shí)一會(huì),保證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é):
在一個(gè)進(jìn)程內(nèi)的所有線程共享全局變量,很方便在多個(gè)線程間共享數(shù)據(jù)
缺點(diǎn)就是,線程是對(duì)全局變量隨意遂改可能造成多線程之間對(duì)全局變量的混亂(即線程非安全)
多線程-共享全局變量問題
多線程開發(fā)可能遇到的問題
假設(shè)兩個(gè)線程t1和t2都要對(duì)全局變量g_num(默認(rèn)是0)進(jìn)行加1運(yùn)算,t1和t2都各對(duì)g_num加10次,g_num的最終的結(jié)果應(yīng)該為20。
但是由于是多線程同時(shí)操作,有可能出現(xiàn)下面情況:
在g_num=0時(shí),t1取得g_num=0。此時(shí)系統(tǒng)把t1調(diào)度為”sleeping”狀態(tài),把t2轉(zhuǎn)換為”running”狀態(tài),t2也獲得g_num=0
然后t2對(duì)得到的值進(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都對(duì)g_num加1,但結(jié)果仍然是g_num=1
編寫代碼測(cè)試如下:
[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個(gè)線程對(duì)同一個(gè)全局變量操作之后的最終結(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個(gè)線程對(duì)同一個(gè)全局變量操作之后的最終結(jié)果是:200
[root@server01 many_task]#
兩個(gè)線程雖然執(zhí)行很快,但是g_num恰好就是100+100=200的結(jié)果,是正確的。不過,這個(gè)數(shù)量少,可能看不出問題來(lái)。
測(cè)試示例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個(gè)線程對(duì)同一個(gè)全局變量操作之后的最終結(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個(gè)線程對(duì)同一個(gè)全局變量操作之后的最終結(jié)果是:19108796
[root@server01 many_task]#
正確的結(jié)果應(yīng)該是:20000000
結(jié)論
如果多個(gè)線程同時(shí)對(duì)同一個(gè)全局變量操作,會(huì)出現(xiàn)資源競(jìng)爭(zhēng)問題,從而數(shù)據(jù)結(jié)果會(huì)不正確
到此這篇關(guān)于Python 多線程共享變量的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Python 多線程共享變量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Pytorch中的數(shù)據(jù)轉(zhuǎn)換Transforms與DataLoader方式
這篇文章主要介紹了Pytorch中的數(shù)據(jù)轉(zhuǎn)換Transforms與DataLoader方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
Python基礎(chǔ)教程之tcp socket編程詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了Python基礎(chǔ)教程之tcp socket編程詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02
pycharm下查看python的變量類型和變量?jī)?nèi)容的方法
今天小編就為大家分享一篇pycharm下查看python的變量類型和變量?jī)?nèi)容的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2018-06-06
python中如何利用matplotlib畫多個(gè)并列的柱狀圖
python是一個(gè)很有趣的語(yǔ)言,可以在命令行窗口運(yùn)行,下面這篇文章主要給大家介紹了關(guān)于python中如何利用matplotlib畫多個(gè)并列的柱狀圖的相關(guān)資料,需要的朋友可以參考下2022-01-01
python實(shí)現(xiàn)類的靜態(tài)變量用法實(shí)例
這篇文章主要介紹了python實(shí)現(xiàn)類的靜態(tài)變量用法,實(shí)例分析了Python中基于數(shù)組實(shí)現(xiàn)靜態(tài)隊(duì)列的相關(guān)使用技巧,需要的朋友可以參考下2015-05-05
python 反編譯exe文件為py文件的實(shí)例代碼
這篇文章主要介紹了python 反編譯exe文件為py文件的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06
python 計(jì)算積分圖和haar特征的實(shí)例代碼
今天小編就為大家分享一篇python 計(jì)算積分圖和haar特征的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2019-11-11
pd.to_datetime中時(shí)間object轉(zhuǎn)換datetime實(shí)例
本文主要介紹了pd.to_datetime中時(shí)間object轉(zhuǎn)換datetime實(shí)例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06

