Python_關於多線程下變量賦值取值的一點研究


 

關於多線程下變量賦值取值的一點研究

 

by:授客 QQ1033553122

1.代碼實踐1

#!/usr/bin/env python
# -*- coding:utf-8 -*-

__author__ = 'shouke'

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import threading
import time

class TestClass:
    def __init__(self, num):
        self.num = num

global_var = 0
def testfn(num, obj):
    global  global_var
    global_var = num
    local_var = num * 2
    obj.num = num * 2
    time.sleep(5)

    print("thread id:", threading.get_ident(), 'num:', num, 'obj.num:', obj.num, 'local_var:', local_var, 'global_var:', global_var)

for i in range(0, 5):
    # # 多線程執行性能監控
    thread = threading.Thread(target=testfn,
                              name="testfn"+str(i),
                              args=(i, TestClass(i)))
    thread.start()

 

Python_關於多線程下變量賦值取值的一點研究

 

 

 

結論:

1、如下,通過args給線程即將調用函數(為方便描述,暫且稱它為 “線程函數”)傳遞參數,可以做到每個線程都使用各自的參數去調用線程函數。

thread = threading.Thread(target=testfn,
                              name="testfn"+str(i),
                              args=(i, TestClass(i)))

2、如下,線程函數里的局部變量(例中除去global_var之外的變量),都存儲在棧內存中,而每個線程都有自己的棧內存,彼此獨立,所以,每個線程對局部變量的賦值,讀取操作互不影響。也就是說,多線程並發的情況下,局部變量是“安全”的,而全局變量存儲在堆內存中,堆內存為所有線程共享,對所有線程都是可見的,所以兩個以上的線程訪問全局變量時,就會出現所謂的“不安全”,如下,第一個線程訪問了全局變量 global_var,賦值為對應的num,然后中間sleep5秒,在此期間,另一個線程訪問了全局變量,賦值為另一個num,然后第一個線程醒來了,發現全局變量 global_var 已經不是它要的值了。

def testfn(num, obj):
    global  global_var
    global_var = num
    local_var = num * 2
    obj.num = num * 2
    time.sleep(5)

2.代碼實踐2

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import threading
import time


thread_local_obj = threading.local()

class TestClass:
    def __init__(self, num):
        self.num = num

global_var = 0
def testfn(num, obj):
    global  global_var
    global_var = num
    local_var = num * 2
    obj.num = num * 2

    thread_local_obj.obj = obj
    time.sleep(5)


    other_task()

    print("thread id:", threading.get_ident(), 'num:', num, 'obj.num:', obj.num, 'local_var:', local_var, 'global_var:', global_var)

def other_task():
    print("thread id:", threading.get_ident(), 'obj.num:', thread_local_obj.obj.num , threading.currentThread().name)


for i in range(0, 5):
    # # 多線程執行性能監控
    thread = threading.Thread(target=testfn,
                              name="testfn"+str(i),
                              args=(i, TestClass(i)))
    thread.start()

 


Python_關於多線程下變量賦值取值的一點研究

 


如上,線程函數中調用了另一個函數,我們希望在這個函數中做些操作,比如讀取和線程關聯的對象的屬性值、修改屬性值,這個按常規思維也可以通過傳遞函數參數來實現,  如下 

other_task(obj):

print(obj.num)

問題是,線程函數里可能會調用多個函數,被調用的每個函數也可能會調用多個函數,所有這些函數都可能用到線程關聯的對像,這樣的話,需要逐層傳遞參數,很麻煩

 

解決方案:

創建全局對象,如下

thread_local_obj = threading.local()

然后在 線程函數 里通過 thread_local_obj.attr = xxx 的方式,綁定線程關聯的東西,其它地方使用時,會自動匹配與線程關聯的值

 

 


免責聲明!

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



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