以下的描述及示例摘录自网上,但其内容经过了整理和编辑。
“Thread Local Storage的功用是什么呢?它主要是为了避免多个线程同时访存同一全局变量或者静态变量时所导致的冲突,尤其是多个线程同时需要修改这一变量时。为了解决这个问题,我们可以通过TLS机制,为每一个使用该全局变量的线程都提供一个变量值的副本,每一个线程均可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。而从全局变量的角度上来看,就好像一个全局变量被克隆成了多份副本,而每一份副本都可以被一个线程独立地改变。”
“TLS也可以用于线程同步机制,它能够被用来解决多线程中的对同一变量的访问冲突。在普通的同步机制中,是通过对象加锁来实现多个线程对同一变量的安全访问的。这时该变量是多个线程共享的,使用这种同步机制需要很细致地分析在什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放该对象的锁等等很多。所有这些都是因为多个线程共享了资源造成的,同时,加同步锁也是一个可能会影响性能的瓶颈。TLS从另一个角度来解决多线程的并发访问,它为每一个线程维护一个和该线程绑定的变量的副本,从而隔离了多个线程的数据,每一个线程都拥有自己的变量副本,因而也就没有必要对该变量进行同步了。TLS提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的整个变量封装进TLS,或者把该对象的特定于线程的状态封装进TLS。”
示例1:直接利用Win32 API实现TLS
直接利用Win32 API实现TLS
#include "stdafx.h"
#include "windows.h"
#include "iostream"
using namespace std;
typedef struct {
DWORD dwFrequency;
DWORD dwDuration;
} soundParams;
DWORD g_nTlsIndex; //!!
void ParamsAlloc()
{
soundParams *params;
params=(soundParams*)new soundParams;
params->dwFrequency=GetTickCount() & 0x00000FFF;
params->dwDuration=100;
cout<<"使用频率:"<<params->dwFrequency<<"\t延时:"<<params->dwDuration<<endl;
TlsSetValue(g_nTlsIndex,params); //!!
}
void ParamsFree()
{
soundParams *params;
params=(soundParams*)TlsGetValue(g_nTlsIndex); //!!
delete params;
}
void ToBeep(void)
{
soundParams *params;
params=(soundParams*)TlsGetValue(g_nTlsIndex); //!!
::Beep(params->dwFrequency,params->dwDuration);
}
void SoundThread()
{
ParamsAlloc();
for (DWORD i=0;i<8;i++) {
ToBeep();
Sleep(1000);
}
ParamsFree();
}
int _tmain(int argc,_TCHAR *argv[])
{
HANDLE soundHandles[3];
DWORD dwThreadID;
DWORD dwCount;
g_nTlsIndex=TlsAlloc(); //!!
for(dwCount=0;dwCount<3;dwCount++) {
soundHandles[dwCount]=CreateThread(NULL,0,
(LPTHREAD_START_ROUTINE)SoundThread,0,0,
&dwThreadID);
Sleep(1500);
}
WaitForMultipleObjects(3,soundHandles,TRUE,INFINITE);
TlsFree(g_nTlsIndex); //!!
return 0;
}
示例2:使用编译器支持实现TLS
利用编译器支持实现TLS
#include "stdafx.h"
#include "windows.h"
#include "iostream"
using namespace std;
typedef struct {
DWORD dwFrequency;
DWORD dwDuration;
} soundParams;
__declspec(thread) soundParams *g_pParams; //!!
void SoundThread()
{
g_pParams=(soundParams*)new soundParams;
g_pParams->dwFrequency=GetTickCount() & 0x00000FFF;
g_pParams->dwDuration=100;
cout<<"使用频率:"<<g_pParams->dwFrequency<<"\t延时:"<<g_pParams->dwDuration<<endl;
for(DWORD i=0;i<8;i++) {
::Beep(g_pParams->dwFrequency,g_pParams->dwDuration);
Sleep(1000);
}
delete g_pParams;
}
int _tmain(int argc,_TCHAR *argv[])
{
HANDLE soundHandles[3];
DWORD dwThreadID;
DWORD dwCount;
for (dwCount=0;dwCount<3;dwCount++) {
soundHandles[dwCount]=CreateThread(NULL,0,
(LPTHREAD_START_ROUTINE)SoundThread,0,0,
&dwThreadID);
Sleep(1500);
}
WaitForMultipleObjects(3,soundHandles,TRUE,INFINITE);
return 0;
}