複製鏈接
請複製以下鏈接發送給好友

TLSAlloc()

鎖定
縮寫為TLS。進程中的全局變量函數內定義的靜態(static)變量,是各個線程都可以訪問的共享變量。在一個線程修改的內存內容,對所有線程都生效。這是一個優點也是一個缺點。説它是優點,線程的數據交換變得非常快捷。説它是缺點,一個線程死掉了,其它線程也性命不保; 多個線程訪問共享數據,需要昂貴的同步開銷,也容易造成同步相關的BUG。
中文名
TLSAlloc()
縮    寫
TLS
性    質
共享變量
特    點
對所有線程都生效

目錄

TLSAlloc()簡介

如果需要在一個線程內部的各個函數調用都能訪問、但其它線程不能訪問的變量(被稱為static memory local to a thread 線程局部靜態變量),就需要新的機制來實現。這就是TLS。
線程局部存儲在不同的平台有不同的實現,可移植性不太好。幸好要實現線程局部存儲並不難,最簡單的辦法就是建立一個全局表,通過當前線程ID去查詢相應的數據,因為各個線程的ID不同,查到的數據自然也不同了。
大多數平台都提供了線程局部存儲的方法,無需要我們自己去實現:

TLSAlloc()linux

int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
int pthread_key_delete(pthread_key_t key);
void *pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);

TLSAlloc()Win32

方法一:每個線程創建時系統給它分配一個LPVOID指針數組(叫做TLS數組),這個數組從C編程角度是隱藏着的不能直接訪問,需要通過一些C API函數調用訪問。首先定義些DWORD線程全局變量或函數靜態變量,準備作為各個線程訪問自己的TLS數組的索引變量。一個線程使用TLS時,第一步在線程內調用TlsAlloc()函數,為一個TLS數組索引變量與這個線程的TLS數組的某個槽(slot)關聯起來,例如獲得一個索引變量:
global_dwTLSindex=TLSAlloc();
注意,此步之後,當前線程實際上訪問的是這個TLS數組索引變量的線程內的拷貝版本。也就説,不同線程雖然看起來用的是同名的TLS數組索引變量,但實際上各個線程得到的可能是不同DWORD值。其意義在於,每個使用TLS的線程獲得了一個DWORD類型的線程局部靜態變量作為TLS數組的索引變量。C/C++原本沒有直接定義線程局部靜態變量的機制,所以在如此大費周折。
第二步,為當前線程動態分配一塊內存區域(使用LocalAlloc()函數調用),然後把指向這塊內存區域的指針放入TLS數組相應的槽中(使用TlsSetValue()函數調用)。
第三步,在當前線程的任何函數內,都可以通過TLS數組的索引變量,使用TlsGetValue()函數得到上一步的那塊內存區域的指針,然後就可以進行內存區域的讀寫操作了。這就實現了在一個線程內部這個範圍處處可訪問的變量。
最後,如果不再需要上述線程局部靜態變量,要動態釋放掉這塊內存區域(使用LocalFree()函數),然後從TLS數組中放棄對應的槽(使用TlsFree()函數)。