如果一個變量是全局的,那么所有線程訪問的是同一份,某一個線程對其修改會影響其他所有線程。如果我們需要一個變量在每個線程中都能訪問,並且值在每個線程中互不影響,這就是TLS。
線程局部存儲在不同平台有不同的實現,可移植性不好。線程局部存儲不難實現,最簡單的辦法是建立一個全局表,通過當前線程ID去查詢相應的數據,因為各個線程ID去查詢相應的數據,因為各個線程的ID不同,查到的數據自然也不同。
分兩種:
1.靜態TLS
_declspec(thread) DWORD data=0;
聲明了_declspec(thread)的變量,會為每一個線程創建一個單獨的拷貝。
2.動態TLS
TEB結構中,有個指針指向線程TLS數組,稱為_tls_array,利用這個數組指針可以管理線程相關的局部變量,這個數組由TLS_MINIMUM_AVAILABLE個元素組成,在WINNT.H文件中該值被定義為64個。
TlsAlloc函數 分配數組索引
DWORD WINAPI TlsAlloc(void);
系統對進程中的標志位進行檢索並找到一個FREE標志,然后系統會將該標志從FREE改為INUSE並讓TlsAlloc返回該標志位在位數組中的索引。
成功返回索引,失敗返回TLS_OUT_OF_INDEXES。
TlsSetValue函數 設置變量值
BOOL WINAPI TlsSetValue( DWORD dwTlsIndex, //索引值,表示在數組中的具體位置 LPVOID lpTlsValue //要設置的值 );
當一個線程調用TlsSetValue函數成功時,他會修改自己的PVOID數組,但它無法修改另一個線程TLS值。(只修改自己的)
TlsGetValue函數獲取變量值
LPVOID WINAPI TlsGetValue( DWORD dwTlsIndex //索引值,表示在數組中的具體位置 );
返回在索引為dwTlsIndex 的TLS元素中保存的值,TlsGetValue只會查看屬於調用線程的數組。(只能查看自己的)
TlsFree函數 釋放索引
BOOL WINAPI TlsFree( DWORD dwTlsIndex //標記的索引值
)
函數會將進程內的標志位數組中對應的INUSE標志重新設回FREE,還會將所有線程中該元素的內容設置為0.