C/C++運行庫提供了TLS(線程局部存儲),在多線程還未產生時,能夠將數據與正在執行的線程關聯。strtok()函數就是一個很好的例子。與它一塊兒的還有strtok_s(),_tcstok_s()等等函數,其實_tcs 是 wcs 的另一種寫法,表示寬字符存儲,_s 是微軟定義的安全函數,一般比普通函數多一個參數。以_tcstok_s()爲例,ios
int main(int argc, char* argv[])
{
wchar_t Source[] = L"192.168.255.255";
wchar_t doc[] = L".";
wchar_t* next_token;
wchar_t* Dest = _tcstok_s(Source, doc, &next_token); //strtok_s
int i = 1;
while (Dest != NULL)
{
printf("Dest[%d]: %S\r\n", i, Dest);
Dest = _tcstok_s(NULL, doc, &next_token);
i++;
}
return 0;
}編程
若是提示函數不認識,添加頭文件 #include <tchar.h>windows
代碼很簡單,將源字符串以 「.」爲分隔符分開,並輸出。注意第二次調用_tcstok_s函數時,第一參數傳NULL,這是由於第一次調用時已經將字符串保存在本身的靜態變量中,後面再使用就能夠引用保存的地址。安全
但在多線程編程下,第一個線程調用_tcstok_s,當它再次調用以前,另外一個線程也可能調用它。這樣就致使第一次的內容被覆蓋。這就用到TLS的內容了。多線程
1.靜態TLS函數
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;spa
__declspec(thread) int value = 0;線程
DWORD WINAPI ThreadProc(LPVOID Param);索引
int main(int argc, char* argv[])
{
value = 1;
HANDLE ThreadHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);token
WaitForSingleObject(ThreadHandle, INFINITE);
cout << "main " << value << endl;
return 0;
}
DWORD WINAPI ThreadProc(LPVOID Param)
{
value = 10;
cout << value << endl;
return 0;
}
__declspec(thread) 這個修飾符告訴編譯器,將這個值放在.tls段中,若是不寫,會放在.data段裏。
結果:
定義了__declspec(thread) 輸出 10 main 1
沒定義__declspec(thread) 輸出 10 main 10
2.動態TLS
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
int __Index[3] = { 0 };
char Name[3][20] = { {"qwe"},{"asd"},{"zxc"} };
DWORD WINAPI ThreadProc(LPVOID Param);
int main(int argc, char* argv[])
{
int i = 0;
DWORD ThreadID[3] = { 0 };
HANDLE ThreadHandle[3] = { 0 };
for (; i < 3; i++)
{
__Index[i] = TlsAlloc(); // 對位標誌進行檢索,找到一個FREE標誌,其實就是預約了一個索引
if (__Index[i] <= TLS_MINIMUM_AVAILABLE)
{
ThreadHandle[i] = CreateThread(NULL, 0, ThreadProc, (LPVOID)(Name[i]), 0, &ThreadID[i]);
}
}
WaitForMultipleObjects(3, ThreadHandle, TRUE, INFINITE);
return 0;
}
DWORD WINAPI ThreadProc(LPVOID Param)
{
char* key = new char[20];
memcpy(key, (char*)Param, 20);
TlsSetValue(__Index[0], key); //將值與索引關聯,注意,微軟實現它時,犧牲了錯誤檢查,即便錯誤的索引,也會分配
for (int i = 0; i < 10; i++)
{
Sleep(1);
printf("%s\r\n", (char*)TlsGetValue(__Index[0])); // 返回 索引中的值
}
free(key);
return 0;
}
通常來講,這兩種TLS在建立DLL時更加有用。