Threading Local

      在〈Threading Local〉中尚無留言

執行緒區域與全域變數

下面代碼runnable()是二個執行緒要執行的任務. Threa 1會產生一個Student物件 s, Thread 2也會產生另一個Student物件 s. 這二個是不同的物件, 因為s 是runnable()的區域變數. 所以Thread1就不會干擾Thread2.

import threading
class Student:
    def __init__(self, score):
        self.score=score;
    def getScore(self):
        return self.score;
def runnable(i):
    s=Student(i);
    calculate(s)
    print('%s, %d' % (threading.current_thread().name,s.getScore()));
def calculate(s):
    s.score=pow(s.score, 1/2)*10
if __name__ == '__main__':
    t1 = threading.Thread(target=runnable, name='Thread-1', args=(9,))
    t2 = threading.Thread(target=runnable, name='Thread-2', args=(40,))
    t1.start()
    t2.start()
結果 :
Thread-1, 30
Thread-2, 63

這麼寫有一個困擾, 就是runnable()又去調用calculate(), 然後又必需把s 傳遞給calculate(), 如果calculate()又去調用別的函數, 勢必又要把s再傳下去. 這樣一層一層的傳, 那還得了.

那如果把s變成全域變數, 不就解決了嗎?? 請注意, thread1跟thread2是不用的Student物件喔, 所以變成全域變數是行不通的.

Threading Local

ThreadLocal就是一個容器, 先宣告在全域變數中. 然後把每個執行緒所需的區域變數指定給它. 後續在其他的函數中, 只要使用threading local, 就會把對應執行緒的區域變數取出. 如此就不需要傳遞了.

為何Threading local如此神奇呢, 說穿了也沒什麼了不起, 其實就是在放進Threading local時, 它偷偷記錄了Thread的名字, 然後將此名字對應到變數的名稱.

import threading
school=threading.local()
class Student:
    def __init__(self, score):
        self.score=score;
    def getScore(self):
        return self.score;
def runnable(i):
    school.student=Student(i)
    calculate()
    print('%s, %d' % (threading.current_thread().name,school.student.getScore()));
def calculate():
    school.student.score=pow(school.student.score, 1/2)*10
if __name__ == '__main__':
    t1 = threading.Thread(target=runnable, name='Thread-1', args=(9,))
    t2 = threading.Thread(target=runnable, name='Thread-2', args=(40,))
    t1.start()
    t2.start()
結果:
Thread-1, 30
Thread-2, 63

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *