python多執行緒-共享全域性變數
目錄
- 多執行緒-共享全域性變數問題
多執行緒-共享全域性變數
多執行緒-共享全域性變數
import threading import time g_num = 200 def test1(): global g_num for i in range(5): g_num += 1 print("--test1, g_num = %d--" % g_num) def test2(): global g_num print("--test2, g_num = %d--" % g_num) if __name__ == "__main__": print("--執行執行緒之前, g_num = %d--" % g_num) t1 = threading.Thread(target=test1) t1.start() # 延時一會兒,確保執行緒t1中的事情能做 time.sleep(1) t2 = threading.Thread(target=test2) t2.start()
執行結果:
--執行執行緒之前, g_num = 200-- --test1, g_num = 205-- --test2, g_num = 205--
在上面的程式中。test1函式
迴圈五次,每次將g_num
全域性變數加一併列印g_num
的值,在test2函式
中僅僅列印g_num
的值。在t1執行緒中執行test1函式,在t2執行緒中執行test2函式,並在執行t2執行緒之前,延時一秒中來保證t1執行緒執行完畢。
列表當作實參傳遞到執行緒中
import threading import time def test1(nums): nums.append(54) print("--test1, nums=", nums) g_nums = [1, 8, 9] def test2(nums): # 確保test1中執行完畢 time.sleep(1) print("--test2, nums=", nums) if __name__ == "__main__": t1 = threading.Thread(target=test1, args=(g_nums,)) t1.start() t2 = threading.Thread(target=test2, args=(g_nums,)) t2.start()
執行結果:
--test1, nums= [1, 8, 9, 54] --test2, nums= [1, 8, 9, 54]
總結
- 在一個程序內的所有執行緒共享全域性變數,很方便在多個執行緒間共享資料
- 缺點就是,執行緒是對全域性變數隨意修改可能造成多執行緒之間對全域性變數的混亂(即執行緒非安全)
多執行緒-共享全域性變數問題
多執行緒開發可能遇到的問題
假設兩個執行緒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
測試1
import threading import time g_num = 0 def test1(num): global g_num for i in range(num): g_num += 1 print("--test1, g_num = %d--" % g_num) def test2(num): global g_num for i in range(num): g_num += 1 print("--test2, g_num = %d--" % g_num) if __name__ == "__main__": print("--建立執行緒之前, g_num = %d--" % g_num) t1 = threading.Thread(target=test1, args=(100,)) t1.start() t2 = threading.Thread(target=test2, args=(100,)) t2.start() while len(threading.enumerate()) != 1: time.sleep(1) print("最終結果為:g_num=%d" % g_num)
執行結果:
--建立執行緒之前, g_num = 0-- --test1, g_num = 100-- --test2, g_num = 200-- 最終結果為:g_num=200
測試2
在測試1的基礎上,向test1和test2方法傳入的引數的值為:9999999
執行結果:
--建立執行緒之前, g_num = 0-- --test1, g_num = 13554011-- --test2, g_num = 13571206-- 最終結果為:g_num=13571206
很顯然,期待的結果為:9999999 + 9999999 = 19999998,而執行結果為:13571206。