20.5 线程本地存储
来源:互联网 发布:元数据被拒绝 编辑:程序博客网 时间:2024/06/05 03:31
摘录于《Windows程序(第5版,珍藏版).CHarles.Petzold 著》P955
在一个多线程程序中,全局变量和所有分配的内存一样,是被程序的所有线程共享的。函数中的局部静态变量也被使用这个函数的所有线程共享。函数中的局部自动变量分配在每个线程自己的堆栈上,所以是线程私有的。(然而这种变量使用的内存在函数结束后接被释放了。)
在有的情况下,我们需要一种既是线程私有,又可以一直存在的存储单元,比如我们前面提到的 C 函数 strtok 就需要用到这种数据。标准 C 语言本身没有这种支持,但是 Windows 通过四个 API 函数提供了一种机制,让我们能够使用静态的线程私有变量。微软对 C 语言的扩展也支持这种机制。这就是线程本地存储。
下面我们演示如何使用线程本地存储的 API。
首先定义一个包含所有静态私有数据的结构,比如:
typedef struct{ int a; int b;}DATA, * PDATA;然后,主线程调用 API 函数 TlsAlloc 以获取一个索引值:
dwTlsIndex = TlsAlloc();这个索引值可以存储在一个全局变量中,或者通过参数结构被传递给线程函数。
线程函数一开始先为这个数据结构分配内存并调用 API 函数 TlsSetValue。函数 TlsSetValue 的调用需要用到我们前面获取的索引值 dwTlsIndex:
TlsSetValue(dwTlsIndex, GlobalAlloc(GPTR, sizeof(DATA));这个函数将一个指针(指向一个线程本地数据结构)和一个特定的线程与特定的线程索引关联起来。现在,任何一个函数,包括原来的线程函数,可以用下面的代码来访问这个指针:
PDATA pdata;...pdata = (PDATA) TlsGetValue(dwTlsIndex);现在,它可以设置或使用 pdata->a 和 pdata->b。在线程函数终止运行之前,它会释放已分配的内存:
GlobalFree (TlsGetValue(dwTlsIndex));当所有使用这个本地存储结构的线程都结束后,我们需要在主线程释放其索引:
TlsFree (dwTlsIndex);
为了更好地理解线程本地存储的机制,让我们来分析分析这些函数是如何被实现的。(我自己并不确定 Windows 是怎么实现的,但是下面的描述应该比较接近。)首先,TlsAlloc 会分配一块内存(初始长度为 0 字节)并返回一个索引值,用作这块内存的指针。每当用该索引值调用 TlsSetValue 的时候,这块内存被重新分配以增加 8 个字节。这 8 个字节用以保存调用该函数的线程的 ID(可以通过调用函数 GetCurrentThreadId 得到)以及传给 TlsSetValue 函数的指针。TlsGetVal 使用线程 ID 搜索索引表并返回相应的指针。TlsFree 最终会释放 TlsAlloc 分配的内存。所以,这个实现机制并不复杂,我们自己实现也不困难。当然,既然 Windows 已经实现了,我们直接用就是了。
此外,微软还扩充了 C 语言以加入这个机制,使用起来更简单。只需要在每个线程需要区分的变量定义之前插入一个特定的前置符__declspec (thread)即可,比如要定义全局静态变量,可使用
__declspec (thread) int iGlobal = 1;而要定义函数内部的静态变量,可使用
__declspec (thread) static int iLocal = 2;
- 20.5 线程本地存储
- 线程本地存储 (TLS)
- 线程本地存储 (TLS)
- 线程本地存储 (TLS)
- 线程本地存储(TLS)
- DLL 线程本地存储
- 线程本地存储 (TLS)
- 线程本地存储
- DLL, 线程本地存储
- 线程本地存储
- C++线程本地存储
- 线程本地存储
- 线程本地存储:pthread_key_t
- 线程本地存储
- 线程本地存储实例
- 线程本地存储ThreadLocal
- [转]线程本地存储 (TLS)
- 线程本地存储(TLS)
- orm2 中文文档 4.3 extendsTo(一对一关系)
- python项目之 英汉词典 带GUI tkinter
- Android绘图机制(四)——使用HelloCharts开源框架搭建一系列炫酷图表,柱形图,折线图,饼状图和动画特效,抽丝剥茧带你认识图表之美
- uva272
- 用结构体变量和结构体变量的指针做参数函数
- 20.5 线程本地存储
- (已测)【ASP.NET 基础】图片上传和显示
- JavaScript进阶(五)js中取小数整数部分函数
- [RunTime练习二]属性的遍历
- What’s New with Multitasking ---- IOS7多任务 (Multitasking)
- 简单认识Yum
- VS2015添加SQL SERVER项目失败
- EclipseJavaEE 修改tomcat的默认端口
- hdoj5137How Many Maos Does the Guanxi Worth【最短路】