使用場景:
1. 在復制文件時,一般都是一個線程調用一個接口復制文件,這時候需要緩存數據,如果每個文件都需要創建獨立的緩存,那麼內存碎片是很大的.
如果創建一個static的內存區,當多線程調用同一個接口時,多個線程同時使用同一個static緩存會造成數據污染.最好的辦法是這個緩存只對這個線程可見,
當線程創建時創建緩存區,當線程結束時銷毀緩存區.
2. 代碼裡有注釋:
test.cpp
#include#include pthread.h #include #include #include typedef enum kTLSKey1 { kTLSKeyCopyFileBuf = 0, kTLSKeyOthers, kTLSKeyMax }kTLSKey; static pthread_key_t gTLSKey[kTLSKeyMax]; static int gTLSKeySize[kTLSKeyMax] = {4194304,4096}; // 這個只是測試等待線程全部結束用的,和TLS沒什麼關系. static pthread_barrier_t barrier = NULL; static int THREADCOUNT = 10; // 我們自定義的庫提供的接口1 void StartWork(kTLSKey type) { pthread_key_t& key = gTLSKey[type]; pthread_key_create(&key,NULL); } // 我們自定義的庫提供的接口2 void EndWork(kTLSKey type) { pthread_key_t& key = gTLSKey[type]; pthread_key_delete(key); } // 我們自定義的庫提供的接口3 // data參數只是為了證明TLS的變量是綁定線程的. void MyCopyFile(const char* from, const char* to,void* data) { pthread_key_t& key = gTLSKey[kTLSKeyCopyFileBuf]; char* lpvData = (char*)pthread_getspecific(key); assert(lpvData == data); Sleep(100); } void* ThreadFunc(void* data) { int size = gTLSKeySize[kTLSKeyCopyFileBuf]; pthread_key_t& key = gTLSKey[kTLSKeyCopyFileBuf]; char* buf = (char*)malloc(size); std::cout << GetCurrentThreadId() << Create buf size: << size << : << (int*)buf << std::endl; pthread_setspecific(key, buf); // 申請的內存存放到TLS裡. // 每個線程復制100個文件 for (int i = 0; i < 100; ++i) { MyCopyFile(C:\infoworld.txt,E:\infoworld.txt,buf); } free(buf); std::cout << ThreadFunc: << GetCurrentThreadId() << finish << std::endl; pthread_barrier_wait(&barrier); return NULL; } void TestPthreadLocalStorage() { StartWork(kTLSKeyCopyFileBuf); // 在主程序初始化. pthread_barrier_init(&barrier,NULL, THREADCOUNT+1); // 主線程也是,所以+1 // 模擬 THREADCOUNT 個線程同時調用接口 MyCopyFile. for (int i = 0; i < THREADCOUNT; ++i) { pthread_t t; pthread_create(&t,NULL,ThreadFunc,NULL); pthread_detach(t); } pthread_barrier_wait(&barrier); EndWork(kTLSKeyCopyFileBuf); // 在主程序釋放. } int main(int argc, char const *argv[]) { setvbuf(stdout,NULL,_IONBF,0); std::cout << test thread local storage. << std::endl; TestPthreadLocalStorage(); std::cout << end thread local storage. << std::endl; return 0; }
輸出:
test thread local storage. 5168 Create buf size: 4194304:0x1180020 3892 Create buf size: 4194304:0x1790020 3352 Create buf size: 4194304:0x21a0020 5808 Create buf size: 4194304:0x29b0020 4972 Create buf size: 4194304:0x2dc0020 6812 Create buf size: 4194304:0x31d0020 6132 Create buf size: 4194304:52200x35e0020 Create buf size: 4194304:0x39f0020 6124 Create buf size: 4194304:0x3e00020 6864 Create buf size: 4194304:0x4210020 ThreadFunc: 5168 finish ThreadFunc: 3892 finish ThreadFunc: 6812 finish ThreadFunc: 5220 finish ThreadFunc: 4972 finish ThreadFunc: 6132 finish ThreadFunc: 6864 finish ThreadFunc: 3352 finish ThreadFunc: 5808 finish ThreadFunc: 6124 finish end thread local storage.