[并发并行]_[C/C++]_[使用线程本地存储Thread Local Storage(TLS)-win32线程和pthread线程比较]
发布日期:2021-06-30 09:56:21 浏览次数:3 分类:技术文章

本文共 4193 字,大约阅读时间需要 13 分钟。

场景:

1.  需要统计某个线程的对象上创建的个数.

2. 当创建的堆空间需要在线程创建和结束时销毁.

3. 因为范围是线程只能看到自己的存储数据,所以不需要临界区或互斥量来维护自己的堆内存. 假如如果用全局std::map实现,那么必须在put和get时加锁,这是很损耗资源的.

4. 可以用在维护一个连接,比如socket,database连接.

说明:

1. Java也有自己的线程本地存储ThreadLocal

2. pthread的win32版本: 

例子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); }

.

输出:

TestWin32TLSdwTlsIndex 26thread 8452: lpvData=714f50common: thread 8452: lpvData=714f50 : value=8452thread 8460: lpvData=7153d0common: thread 8460: lpvData=7153d0 : value=8460thread 8456: lpvData=715610common: thread 8456: lpvData=715610 : value=8456thread 8464: lpvData=715190common: thread 8464: lpvData=715190 : value=8464TestPthreadTLScommon: thread 8520: lpvData=3b4eb0 : value=8520common: thread 8512: lpvData=3b4ff0 : value=8512common: thread 8516: lpvData=3b4eb0 : value=8516common: thread 8524: lpvData=3b4ff0 : value=8524

参考:

转载地址:https://infoworld.blog.csdn.net/article/details/43992097 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:[MacOSX]_[Time Machine]_[备份失败的解决办法]
下一篇:[并发并行]_[线程同步]_[Windows用户态下的原子访问的互锁函数]

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年05月02日 22时32分47秒