【技术分享】线程本地存储(Thread Local Storage, TLS)

在项目开发中,遇到了关于TLS相关的问题。为了了解该机制的用途,在微软的官网查找了一些资料。

本文参考官方文档, 简单介绍一下TLS的用途与使用方法。

微软官方文档链接

一、简介

线程本地存储(TLS),可以使多个线程,通过TlsGetValue函数,获得各自线程独立的数据。

即,在进程中通过TlsAlloc,可以申请一个索引值(index)。

在不同的线程中,通过TlsSetValue/TlsGetValue,可以获得不同的数据。

注:TlsSetValue/TlsGetValue内部可能是通过线程ID进行了绑定,实现的功能。

二、官方示例(有调整)及个人注解

#include <windows.h>
#include <stdio.h> #define THREADCOUNT 4
DWORD dwTlsIndex; VOID ErrorExit(LPCSTR message);
VOID CommonFunc(VOID);
DWORD WINAPI ThreadFunc(VOID); // main入口函数
int main(VOID)
{
DWORD IDThread;
HANDLE hThread[THREADCOUNT];
int i; // 通过TlsAlloc函数,创建进程的tls索引,保存在dwTlsIndex
if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
{
// 如果返回TLS_OUT_OF_INDEXES,说明创建失败
ErrorExit("TlsAlloc failed");
} // 通过for循环创建多个线程
for (i = 0; i < THREADCOUNT; i++)
{
hThread[i] = CreateThread(NULL, // 默认security属性
0, // 默认stack size
(LPTHREAD_START_ROUTINE)ThreadFunc, // 线程处理函数
NULL, // no thread function argument
0, // use default creation flags
&IDThread); // returns thread identifier // 判定创建线程结果
if (hThread[i] == NULL)
ErrorExit("CreateThread error\n");
} // 等待所有线程执行完毕,退出循环
for (i = 0; i < THREADCOUNT; i++)
WaitForSingleObject(hThread[i], INFINITE); TlsFree(dwTlsIndex); return 0;
} VOID ErrorExit(LPCSTR message)
{
// 输出线程错误消息,并退出进程
fprintf(stderr, "%s\n", message);
ExitProcess(0);
} VOID CommonFunc(VOID)
{
LPVOID lpvData; // 取得dwTlsIndex指向的空间(此时获得的数据是各自线程通过TlsSetValue设置进去的)
lpvData = TlsGetValue(dwTlsIndex);
if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
ErrorExit("TlsGetValue error"); // 可以使用该空间数据
printf("common: thread %d: lpvData=%lx\n",
GetCurrentThreadId(), lpvData); Sleep(5000);
} DWORD WINAPI ThreadFunc(VOID)
{
LPVOID lpvData; // 申请动态空间,每个线程创建独自的空间。
lpvData = (LPVOID)LocalAlloc(LPTR, 256); // 将动态空间绑定到Tls对应的Index空间上
if (!TlsSetValue(dwTlsIndex, lpvData))
ErrorExit("TlsSetValue error"); printf("thread %d: lpvData=%lx\n", GetCurrentThreadId(), lpvData); // 通用处理函数,可以在内部使用TlsGetValue获得的数值
CommonFunc(); // 释放动态空间,每个线程创建独自的空间。
lpvData = TlsGetValue(dwTlsIndex); if (lpvData != 0)
LocalFree((HLOCAL)lpvData); return 0;
}

【GiraKoo】线程本地存储(Thread Local Storage, TLS)的更多相关文章

  1. 线程本地存储(Thread Local Storage, TLS)简单分析与使用

    在多线程编程中, 同一个变量, 如果要让多个线程共享访问, 那么这个变量可以使用关键字volatile进行声明; 那么如果一个变量不想使多个线程共享访问, 那么该怎么办呢? 呵呵, 这个办法就是TLS ...

  2. ionic 通过PouchDB + SQLite来实现app的本地存储(Local Storage)

    首先声明,本教程参考国外网站(http://gonehybrid.com/how-to-use-pouchdb-sqlite-for-local-storage-in-your-ionic-app/) ...

  3. [转]ionic 通过PouchDB + SQLite来实现app的本地存储(Local Storage)

    本文转自:http://www.cnblogs.com/ailen226/p/ionic.html 首先声明,本教程参考国外网站(http://gonehybrid.com/how-to-use-po ...

  4. Atitit usrqbg1821 Tls 线程本地存储(ThreadLocal Storage 规范标准化草案解决方案ThreadStatic

    Atitit usrqbg1821 Tls 线程本地存储(ThreadLocal Storage 规范标准化草案解决方案ThreadStatic 1.1. ThreadLocal 设计模式1 1.2. ...

  5. 线程本地存储TLS(Thread Local Storage)的原理和实现——分类和原理

    原文链接地址:http://www.cppblog.com/Tim/archive/2012/07/04/181018.html 本文为线程本地存储TLS系列之分类和原理. 一.TLS简述和分类 我们 ...

  6. 线程本地存储TLS(Thread Local Storage)的原理和实现——分类和原理

    本文为线程本地存储TLS系列之分类和原理. 一.TLS简述和分类 我们知道在一个进程中,所有线程是共享同一个地址空间的.所以,如果一个变量是全局的或者是静态的,那么所有线程访问的是同一份,如果某一个线 ...

  7. 线程本地存储(动态TLS和静态TLS)

    线程本地存储(TLS) 对于多线程应用程序,如果线程过于依赖全局变量和静态局部变量就会产生线程安全问题.也就是一个线程的使用全局变量可能会影响到其他也使用此全局变量的线程,有可能会造成一定的错误,这可 ...

  8. 利用HTML5开发Android(7)---HTML5本地存储之Database Storage

    在上一篇<HTML5本地存储之Web Storage篇>中,简单介绍了如何利用localStorage实现本地存储:实际上,除了sessionStorage和localStorage外,H ...

  9. .NET:线程本地存储、调用上下文、逻辑调用上下文

    .NET:线程本地存储.调用上下文.逻辑调用上下文 目录 背景线程本地存储调用上下文逻辑调用上下文备注 背景返回目录 在多线程环境,如果需要将实例的生命周期控制在某个操作的执行期间,该如何设计?经典的 ...

  10. C# 线程本地存储 调用上下文 逻辑调用上下文

    线程本地存储 using System; using System.Threading; using System.Threading.Tasks; namespace ConsoleAppTest ...

随机推荐

  1. Thinkpad键盘操作手册与驱动 thinkpad蓝牙键盘KT-1525 manual

    thinklife mechanical keyboard tk500_win10.exe https://pan.baidu.com/s/1pQM3RcgV-phugew6vcKDLw

  2. windows2003 的安装以及安装时遇到的问题

    windows2003 的安装以及安装时遇到的问题 简介:Windows Server 2003是微软于2003年3月28日发布的基于Windows XP/NT5.1开发的服务器操作系统,并在同年4月 ...

  3. JAVA重试机制多种方式深入浅出

    重试机制在分布式系统中,或者调用外部接口中,都是十分重要的. 重试机制可以保护系统减少因网络波动.依赖服务短暂性不可用带来的影响,让系统能更稳定的运行的一种保护机制. 为了方便说明,先假设我们想要进行 ...

  4. Python学习笔记--图像的进一步学习

    演示地图的可视化的实现 示例: 设置全局选项 可以设置出不同的颜色,不会显得很干巴: 国内地图: 那么,我们应当如何找到相对应的颜色的编号呢? 基本步骤: 前往ab173.com网站 然后在,前端那里 ...

  5. 《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(11)-Charles如何模拟弱网环境

    1.前言 张三:"我写的软件好奇怪啊,在网络好的时候一点问题也没有,但是信号差的时候明显卡顿,看来我只能一直蹲在卫生间.电梯或者地铁(信号差)调bug了". Charles:&qu ...

  6. 在wxpython框架写的GUI中调用GIF格式图片,显示在指定行列的方法

    #首先需要从 wx.adv 模块导入 Animation, AnimationCtrl方法 from wx.adv import Animation, AnimationCtrl #然后在面板实现过程 ...

  7. 发布新版博客备份功能:生成 sqlite 数据库文件,vscode 插件可查看

    大家好,最近我们重新开发了园子的博客备份功能,今天发布第一个预览版,欢迎大家试用. 点击博客后台侧边栏的博客备份进入新版博客备份: 点击创建备份按钮创建博客备份任务(目前每天只能创建一次备份),待备份 ...

  8. IO 流分类

    更多内容,前往 IT-BLOG 一.File File 类(磁盘操作)可以用于表示文件和目录的信息,但是它不表示文件的内容.递归地列出一个目录下所有文件: 1 public static void l ...

  9. Spring(Ioc和Bean的作用域)

    Spring Spring为简化开发而生,让程序员只关心核心业务的实现,尽可能的不在关注非业务逻辑代码(事务控制,安全日志等). 1,Spring八大模块 这八大模块组成了Spring 1.1 Spr ...

  10. [原创][luogu]P1217 回文质数 真·生成回文的方法

    不多说,直接看代码,都在注释里 // 中心思想: // * 1. 代入数据只想回文的一半和位数的变化 // * 例. 1001 和 101 都存的是10, 但是位数一个是4, 一个是3 // * 2. ...