Thread Local Storage
来源:互联网 发布:国际数据分析师认证 编辑:程序博客网 时间:2024/04/27 19:15
Instance(单件)机制原本是让代码执行时只有一个实例,但有的时候又希望每个线程各自能有自己的"单件"相互不影响,处理类似的需求最先想到的就是全局表,然后按线程id或是管理线程的key索引到对应的单件上,取全局表的时候需要加锁。 虽然这样也能实现目的,但是代码看上去很不自然。最近发现还是有更自然的方法能实现这一点,就是 TLS 线程本地存储(Thread Local Storage)
用编译器实现这点比较简单,如果是使用动态创建的方式来实现的单件 则需要申请一个key 来绑定使用这个TLS 单件
---------------------------------------------------------------------------------------------------------------------------
Compiler :
---------------------------------------------------------------------------------------------------------------------------
_declspec (thread) InstanceClassA g_ia;
// 这句告诉给编译器此变量为线程内部使用,每个线程都会copy一份给本地用
---------------------------------------------------------------------------------------------------------------------------
windows 和 linux 下用到的api 稍有不同,但用法差不多,主要是通过申请key 绑定 内存对象 ,释放key 释放内存的 方式进行
WIN API :
---------------------------------------------------------------------------------------------------------------------------
static DWORD InstanceClassA::dwTlsIndex;
// 定义一些DWORD线程全局变量或函数静态变量,准备作为各个线程访问自己的TLS数组的索引变量
InstanceClassA::dwTlsIndex= TLSAlloc();
// 当前线程实际上访问的是这个TLS数组索引变量的线程内的拷贝版本。也就说,不同线程虽然看起来用的是同名的TLS数组索引变量,但实际上各个线程得到的可能是不同DWORD值。其意义在于,每个使用TLS的线程获得了一个DWORD类型的线程局部静态变量作为TLS数组的索引变量。C/C++原本没有直接定义线程局部静态变量的机制,所以在如此大费周折
TlsSetValue(InstanceClassA::dwTlsIndex, new InstanceClassA);
// 动态申请单件内存,然后把指向这块内存区域的指针放入TLS数组相应的槽中,绑定上TlsIndex
InstanceClassA* gp_ia = TlsGetValue(InstanceClassA::dwTlsIndex);
// 用 TlsIndex 取得单件
delete gp_ia ;
// 先释放单件内存
TlsFree(InstanceClassA::dwTlsIndex);
// 然后 释放TLS索引变量 ,如果dwTlsIndex先删除了则很难释放其绑定上的InstanceClassA单件了,在这点上 linux 提供了一个更为保险的方法
----------------------------------------------------------------------------------------------------------------------------
LINUX API :
-----------------------------------------------------------------------------------------------------------------------------
static pthread_key_t InstanceClassA::dwTlsIndex;
// 这步骤同win 一样
static void InstanceClassA::destroy(void *p) { delete (InstanceClassA*)p; }
// 为索引提供一个释放绑定对象的方法
pthread_key_create(&InstanceClassA::dwTlsIndex, &InstanceClassA::destroy);
// 创建出索引并且提供释放方法给索引将会绑定的对象
pthread_setspecific(InstanceClassA::dwTlsIndex, new InstanceClassA);
// 绑定单件到索引
InstanceClassA* gp_ia = pthread_getspecific(InstanceClassA::dwTlsIndex);
// 用 索引 取得单件
pthread_key_delete(InstanceClassA::dwTlsIndex);
// 释放掉索引的同时 ,也会调用 InstanceClassA::destroy 释放掉InstanceClassA
-----------------------------------------------------------------------------------------------------------------------------
staticInstanceClassA*GetInstance()
{
InstanceClassA* pm = (InstanceClassA*)pthread_getspecific(InstanceClassA::dwTlsIndex);
// or TlsGetValue(InstanceClassA::dwTlsIndex)
if(!pm) pthread_setspecific(InstanceClassA::dwTlsIndex,
pm = new InstanceClassA()); // or
TlsSetValue(InstanceClassA::dwTlsIndex, new InstanceClassA)
return pm;
}
- Thread-Local Storage
- TLS (Thread local storage)
- Thread-Local Storage(TLS)
- MSDN:Thread Local Storage
- Thread Local Storage
- Thread-Local Storage
- TLS:Thread Local Storage
- Thread Local Storage
- Thread Local Storage
- TLS:Thread Local Storage
- Thread Local Storage
- Thread Local Storage
- thread local storage
- Thread-Local Storage: TLS
- Thread Local Storage
- Thread Local Storage(TLS)
- Thread Local Storage (TLS)
- C++ Thread Local Storage
- C#弱类型Dataset和强类型Dataset
- beta分布
- 通过金矿模型介绍动态规划
- 用Jsoup进行链接提取
- 文件映射内存使用方法
- Thread Local Storage
- 通过金矿模型介绍动态规划
- WebBrowser页面与WinForm交互技巧
- 长连接与短连接
- 求解sizeof(X)
- 基于稀疏表示的人脸识别 (SRC,LASRC,RASL,MRR)
- WebBrowser页面与WinForm交互技巧
- 信息和图片附件导入导出
- Red Hat Linux 5.4 开启xdm远程访问