场景:
1. 需要统计某个线程的对象上创建的个数.
2. 当创建的堆空间需要根据线程需要创建和结束时销毁时.
3. 因为范围是线程只能看到自己的存储数据,所以不需要临界区或互斥量来维护自己的堆内存. 加入如果用全局std::map实现,那么必须在put和get时加锁,这是很损耗资源的.
4. 可以用在维护一个连接,比如socket,database连接.
说明:
1. Java也有自己的线程本地存储ThreadLocal
例子test_TSL.cpp:
#include "stdafx.h"
#include
#include
#include
#include
#include
#include "pthread.h"
#define THREADCOUNT 4
DWORD dwTlsIndex;
VOID ErrorExit(const char*);
static pthread_barrier_t barrier = NULL;
static pthread_once_t random_is_initialized = PTHREAD_ONCE_INIT;
static pthread_key_t key;
VOID CommonFunc(VOID)
{
LPVOID lpvData;
// Retrieve a data pointer for the current thread.
lpvData = TlsGetValue(dwTlsIndex);
if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
ErrorExit("TlsGetValue error");
// Use the data stored for the current thread.
int64_t* value = (int64_t*)lpvData;
printf("common: thread %d: lpvData=%lx : value=%lld\n",
GetCurrentThreadId(), lpvData,*value);
Sleep(5000);
}
DWORD WINAPI ThreadFunc(VOID)
{
LPVOID lpvData;
// Initialize the TLS index for this thread.
lpvData = (LPVOID) LocalAlloc(LPTR, 8);
if (! TlsSetValue(dwTlsIndex, lpvData))
ErrorExit("TlsSetValue error");
int64_t* value = (int64_t*)lpvData;
*value = GetCurrentThreadId();
printf("thread %d: lpvData=%lx\n", GetCurrentThreadId(), lpvData);
CommonFunc();
// Release the dynamic memory before the thread returns.
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != 0)
LocalFree((HLOCAL) lpvData);
return 0;
}
void TestWin32TLS()
{
DWORD IDThread;
HANDLE hThread[THREADCOUNT];
int i;
// Allocate a TLS index.
if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
ErrorExit("TlsAlloc failed");
//1. 注意,这个dwTlsIndex 并不是从0开始.
printf("dwTlsIndex %ld\n",dwTlsIndex);
// Create multiple threads.
for (i = 0; i < THREADCOUNT; i++)
{
hThread[i] = CreateThread(NULL, // default security attributes
0, // use default stack size
(LPTHREAD_START_ROUTINE) ThreadFunc, // thread function
NULL, // no thread function argument
0, // use default creation flags
&IDThread); // returns thread identifier
// Check the return value for success.
if (hThread[i] == NULL)
ErrorExit("CreateThread error\n");
}
for (i = 0; i < THREADCOUNT; i++)
WaitForSingleObject(hThread[i], INFINITE);
TlsFree(dwTlsIndex);
}
void CommonFuncPthread(void)
{
void* lpvData = pthread_getspecific(key);
int64_t* value = (int64_t*)lpvData;
printf("common: thread %d: lpvData=%lx : value=%lld\n",
GetCurrentThreadId(), lpvData,*value);
}
void* StartPthread(void* data)
{
int64_t *buf = (int64_t*)malloc(256);
*buf = GetCurrentThreadId();
pthread_setspecific(key, buf);
CommonFuncPthread();
free(buf);
pthread_barrier_wait(&barrier);
return NULL;
}
//1.只调用一次,可以放在随意一个work thread执行函数里都可以,会随机找一个线程执行.
//2.类似win32的DLL_PROCESS_ATTACH只执行一次.
void TestPthreadTLS()
{
pthread_key_create(&key, NULL);
pthread_barrier_init(&barrier,NULL, THREADCOUNT + 1);
for(int i = 0; i< THREADCOUNT; ++i)
{
pthread_t t;
pthread_create(&t,NULL,StartPthread,NULL);
pthread_detach(t);
}
//1.等待其他线程执行完.
pthread_barrier_wait(&barrier);
pthread_key_delete(key);
}
DWORD main(VOID)
{
//1.win32TLS
printf("TestWin32TLS\n");
TestWin32TLS();
//1.pthread TLS
printf("TestPthreadTLS\n");
TestPthreadTLS();
return 0;
}
VOID ErrorExit (const char* lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0);
}
.
输出:
TestWin32TLS
dwTlsIndex 26
thread 8452: lpvData=714f50
common: thread 8452: lpvData=714f50 : value=8452
thread 8460: lpvData=7153d0
common: thread 8460: lpvData=7153d0 : value=8460
thread 8456: lpvData=715610
common: thread 8456: lpvData=715610 : value=8456
thread 8464: lpvData=715190
common: thread 8464: lpvData=715190 : value=8464
TestPthreadTLS
common: thread 8520: lpvData=3b4eb0 : value=8520
common: thread 8512: lpvData=3b4ff0 : value=8512
common: thread 8516: lpvData=3b4eb0 : value=8516
common: thread 8524: lpvData=3b4ff0 : value=8524
参考: