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的更多相关文章

  1. 【windows核心编程】线程局部存储TLS

    线程局部存储TLS, Thread Local Storage TLS是C/C++运行库的一部分,而非操作系统的一部分. 分为动态TSL 和 静态TLS 一.动态TLS 应用程序通过调用一组4个函数来 ...

  2. 线程局部存储TLS

    1 .使用线程局部存储的理由 当我们希望这个进程的全局变量变为线程私有时,而不是所有线程共享的,也就是每个线程拥有一份副本时,这时候就可以用到线程局部存储(TLS,Thread Local Stora ...

  3. 线程局部存储tls的使用

    线程局部存储(Thread Local Storage,TLS)主要用于在多线程中,存储和维护一些线程相关的数据,存储的数据会被关联到当前线程中去,并不需要锁来维护.. 因此也没有多线程间资源竞争问题 ...

  4. 线程局部存储TLS(thread local storage)

    同一全局变量或者静态变量每个线程访问的是同一变量,多个线程同时访存同一全局变量或者静态变量时会导致冲突,尤其是多个线程同时需要修改这一变量时,通过TLS机制,为每一个使用该全局变量的线程都提供一个变量 ...

  5. linux中的线程局部存储(TLS)

    http://blog.csdn.net/cywosp/article/details/26469435

  6. PE格式第八讲,TLS表(线程局部存储)

    PE格式第八讲,TLS表(线程局部存储) 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶复习线程相关知识 首先讲解 ...

  7. 线程局部存储(TLS)

    线程局部存储(TLS) 2011-10-11 09:59:28|  分类: Win32---API |  标签:tls   |举报 |字号 订阅   什么是线程局部存储 众所周知,线程是执行的单元,同 ...

  8. 【C# 线程】线程局部存储(TLS)理论部分 ThreadStatic|LocalDataStoreSlot|ThreadLocal<T>

    线程本地存储(TLS:Thread Local Storage) 线程本地存储(Thread Local Storage),字面意思就是专属某个线程的存储空间.变量大体上分为全局变量和局部变量,一个进 ...

  9. 基于TLS(线程局部存储)的高效timelog实现

    什么是timelog? 我们在分析程序性能的时候,会加入的一些logging信息记录每一部分的时间信息 timelog模块的功能就是提供统一的接口来允许添加和保存logging 我们正在用的timel ...

随机推荐

  1. OpenCV入门:(六:基础画图函数)

    有时程序中需要画一些基础的图形,例如直线,矩形,椭圆以及多边形.OpenCV中当然有此类函数. 1.函数介绍 直线line: , , ) img – 图像 pt1 – 直线起点 pt2 – 直线终点 ...

  2. ubuntu12.04停留在grub界面问题

    修改ubuntu 12.04 停留在grub界面的步骤: 1. 在/etc/default/grub配置文件中, 添加一项GRUB_RECORDFAIL_TIMEOUT: GRUB_TIMEOUT=2 ...

  3. 剑指offer-二叉树的镜像18

    题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ ...

  4. 1018 Public Bike Management (30 分)(图的遍历and最短路径)

    这题不能直接在Dijkstra中写这个第一 标尺和第二标尺的要求 因为这是需要完整路径以后才能计算的  所以写完后可以在遍历 #include<bits/stdc++.h> using n ...

  5. N-grams模型、停顿词(stopwords)和标准化处理 - NLP学习(2)

    在上一节<Tokenization - NLP(1)>的学习中,我们主要学习了如何将一串字符串分割成单独的字符,并且形成一个词汇集(vocabulary),之后我们将形成的词汇集合转换成计 ...

  6. gitbook生成的_book文件本地打开后链接失效问题

    Gitbook 生成本地 html 的问题 在本地用 gitbook-cli根据 Summary 生成目录 然后在每个 md 文件里书写内容 然后用 gitbook serve .生成本地 html ...

  7. 学习bash——环境配置

    一.环境配置文件的重要性 Bash在启动时直接读取这些配置文件,以规划好bash的操作环境. 即使注销bash,我们的设置仍然保存. 二.login shell 通过完整的登录流程取得的bash,称为 ...

  8. JavaSE复习(五)网络编程

    客户端:java.net.Socket 类表示.创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信 服务端:java.net.ServerSocket 类表示.创建Ser ...

  9. BST插入与查找

    B树: 二叉查找树,所有左节点都比父节点要小,所有右节点都比父节点要大.查找,插入的时间复杂度为O(logn) public class BTreeTest { public static int[] ...

  10. java-2018-01-17计划

    1.一句英语 包括单词 2.一个java版本的设计模式 参考:https://github.com/iluwatar/java-design-patterns 学习了抽象工厂模式 总结:java的RS ...