码迷,mamicode.com
首页 > 编程语言 > 详细

线程局部存储 TLS

时间:2017-08-07 22:15:07      阅读:263      评论:0      收藏:0      [点我收藏+]

标签:out   word   例子   ble   参数   handle   ken   调用   argv   

C/C++运行库提供了TLS(线程局部存储),在多线程还未产生时,可以将数据与正在执行的线程关联。strtok()函数就是一个很好的例子。与它一起的还有strtok_s(),_tcstok_s()等等函数,其实_tcs 是 wcs 的另外一种写法,表示宽字符存储,_s 是微软定义的安全函数,通常比普通函数多一个参数。以_tcstok_s()为例,

 

int main(int argc, char* argv[])
{

wchar_t Source[] = L"192.168.255.255";
wchar_t doc[] = L".";
wchar_t* next_token;
wchar_t* Dest = _tcstok_s(Source, doc, &next_token); //strtok_s
int i = 1;
while (Dest != NULL)
{
printf("Dest[%d]: %S\r\n", i, Dest);
Dest = _tcstok_s(NULL, doc, &next_token);
i++;
}
return 0;
}

如果提示函数不认识,添加头文件 #include <tchar.h>

代码很简单,将源字符串以 “.”为分隔符分开,并输出。注意第二次调用_tcstok_s函数时,第一参数传NULL,这是因为第一次调用时已经将字符串保存在自己的静态变量中,后面再使用就可以引用保存的地址。

但在多线程编程下,第一个线程调用_tcstok_s,当它再次调用之前,另一个线程也可能调用它。这样就导致第一次的内容被覆盖。这就用到TLS的内容了。

 

1.静态TLS

#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;

__declspec(thread)  int value  = 0;

DWORD WINAPI ThreadProc(LPVOID Param);

int main(int argc, char* argv[])
{
value = 1;
HANDLE ThreadHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);

WaitForSingleObject(ThreadHandle, INFINITE);

cout << "main " << value << endl;
return 0;
}

DWORD WINAPI ThreadProc(LPVOID Param)
{
value = 10;
cout << value << endl;
return 0;
}

__declspec(thread)  这个修饰符告诉编译器,将这个值放在.tls段中,如果不写,会放在.data段里。

结果:

定义了__declspec(thread)     输出 10           main 1

没定义__declspec(thread)     输出 10           main 10

 

2.动态TLS

#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;

int __Index[3] = { 0 };
char Name[3][20] = { {"qwe"},{"asd"},{"zxc"} };
DWORD WINAPI ThreadProc(LPVOID Param);

int main(int argc, char* argv[])
{
int i = 0;
DWORD ThreadID[3] = { 0 };
HANDLE ThreadHandle[3] = { 0 };
for (; i < 3; i++)
{
__Index[i] = TlsAlloc();  // 对位标志进行检索,找到一个FREE标志,其实就是预定了一个索引
if (__Index[i] <= TLS_MINIMUM_AVAILABLE) 
{
ThreadHandle[i] = CreateThread(NULL, 0, ThreadProc, (LPVOID)(Name[i]), 0, &ThreadID[i]);
}
}
WaitForMultipleObjects(3, ThreadHandle, TRUE, INFINITE);
return 0;
}

DWORD WINAPI ThreadProc(LPVOID Param)
{
char* key = new char[20];
memcpy(key, (char*)Param, 20);
TlsSetValue(__Index[0], key);   //将值与索引关联,注意,微软实现它时,牺牲了错误检查,即使错误的索引,也会分配
for (int i = 0; i < 10; i++)
{
Sleep(1);
printf("%s\r\n", (char*)TlsGetValue(__Index[0]));    // 返回 索引中的值

}

free(key);
return 0;
}

 一般来说,这两种TLS在创建DLL时更加有用。

 

线程局部存储 TLS

标签:out   word   例子   ble   参数   handle   ken   调用   argv   

原文地址:http://www.cnblogs.com/kekoukele987/p/7301309.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!