1. 程式人生 > >ThreadLocal是用來做什麼的?

ThreadLocal是用來做什麼的?

真真應了那句話,書讀百遍,其意自現。何況大多數時候,你只需要重複一遍就行了,廢話不多說。

一,首先來看看這樣一些問題的區別:

1. 多程序之間如何通訊?

因為不同的程序會在記憶體中被分配不同的資源。所以多程序之間通訊是一個問題,python的multiprocessing模組一共了一系列的交換方式,Queue, Pipe, Manager。

2. 多執行緒之間如何通訊?

這就不是一個問題,因為執行緒間是共享所在程序變數的。所以通訊不是問題,讓它們同步才是問題,同步暫且不表。

3. 不同程序間執行緒如何通訊?

這也不是個問題,因為這就是兩個程序之間的通訊。

4. 一個執行緒內部如何通訊?

可能乍一看,覺得這也能是個問題?但,這才是真正的問題。

二,下面進入正題,看程式碼

import threading

def a(x):
    print('a thread %d' % x)
    b(x)

def b(x):
    print('b thread %d' % x)

t1 = threading.Thread(target=a, args=(3,))
t2 = threading.Thread(target=a, args=(5,))

t1.start()
t1.join()
t2.start()
t2.join()

Output:
a thread 3
b thread 3
a thread 5
b thread 5

開啟執行緒呼叫a方法,然後a方法呼叫b方法。 可以看到,t1,t2兩個執行緒裡的x是不同的x。

所以,執行緒內部兩個函式通訊,可以用引數來傳遞。但這顯然不是一個好的方法,當函式數量上去或著互動的資料很多,那一層層傳參就崩潰了。

那麼直接用全域性變數?看效果

import threading

x = 0

def a():
    print('a thread %d' % x)
    b()

def b():
    print('b thread %d' % x)

t1 = threading.Thread(target=a)
t2 = threading.Thread(target=a)

t1.start()
t1.join()
t2.start()
t2.join()

Output:
a thread 0
b thread 0
a thread 0
b thread 0

我們的目的是為了讓不同的執行緒,維護不同的x,但是因為x是程序的,所以就只有一份,達不到目的。

三,解決方案

前面達不到目的,是因為程序中的x只有一份,大家都能訪問,那麼我們在程序中把x做成多份,一個執行緒對應一份不就行了?那麼要實現執行緒和特定的x一一對應,那就是map了,在python中,使用dict。

import threading

dict = {}

def a(x):
    dict[threading.current_thread()] = x
    print('a thread %d' % x)
    b()

def b():
    print('b thread %d' % dict[threading.current_thread()])

t1 = threading.Thread(target=a, args=(3,))
t2 = threading.Thread(target=a, args=(5,))

t1.start()
t1.join()
t2.start()
t2.join()

Output:
a thread 3
b thread 3
a thread 5
b thread 5

可以看到,在程序中維護了一個dict,然後用每個執行緒的current_thread()去對映它們各自的x變數。完成了要求。

上面雖然完成了要求,不過怎麼看都是野路子,所以ThreadLocal來了。

import threading

dict = threading.local()

def a(x):
    dict.x = x
    print('a thread %d' % dict.x)
    b()

def b():
    print('b thread %d' % dict.x)

t1 = threading.Thread(target=a, args=(3,))
t2 = threading.Thread(target=a, args=(5,))

t1.start()
t1.join()
t2.start()
t2.join()

Output:
a thread 3
b thread 3
a thread 5
b thread 5

其實原理都一樣,不過是python做得太好,什麼都封裝,有些問題看起來就不那麼直觀了。