[同時並行][C/C++]_[スレッドを使用したThread Local Storage(TLS)-win 32スレッドとpthreadスレッドの比較]


シーン:
1.あるスレッドのオブジェクトに作成する個数を統計する必要がある.
2.作成するヒープスペースはスレッドの作成と終了時に破棄する必要がある.
3.範囲はスレッドが自分の記憶データしか見えないため、臨界領域や反発量を必要とせずに自分のスタックメモリを維持する.グローバルstd::mapで実現する場合、putとgetの間にロックをかけなければならない.これはリソースを損失する.
4.socket、databaseなどの接続を維持するために使用することができる.
説明:
1.Javaにも独自のスレッドがローカルに格納されているThreadLocal
2.pthreadのwin 32バージョン:http://sourceware.org/pthreads-win32/
例test_TSL.cpp:
#include "stdafx.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h> 
#include <windows.h> 
#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
", 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
", 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
",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
"); } 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
", 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
"); TestWin32TLS(); //1.pthread TLS printf("TestPthreadTLS
"); TestPthreadTLS(); return 0; } VOID ErrorExit (const char* lpszMessage) { fprintf(stderr, "%s
", 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

参照先:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686749(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686991(v=vs.85).aspx
http://blog.chinaunix.net/uid-10231348-id-3034751.html
http://blog.csdn.net/liulina603/article/details/17991731
http://linux.die.net/man/3/pthread_once