【技术分享】线程本地存储(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. Double-Checked Locking 双重检查锁问题

    Code Correctness: Double-Checked Locking Abstract Double-checked locking 是一种不正确的用法,并不能达到预期目标. Explan ...

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

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

  3. CSharp读写world文档数据

    背景 在工作中需要对比数据,然后输出一份world文档的对比报告.这需要用C#来读写world文件. 用到的工具 NPOI NPOI 地址:NPOI NPOI版本:2.6.0 个人项目的运行时版本:. ...

  4. 记录hive一次数据倾斜问题的解决以及思考总结

    解决数据倾斜是大数据开发中比较重要的能力,这个现象指的是分布式集群中,由于数据分发的不当,导致某个节点要处理的错误过多,导致整个计算机任务迟迟结束不了,甚至可能节点出现OOM使得任务失败 处理数据倾斜 ...

  5. 剑指 offer 第 3 天

    第 3 天 字符串(简单) 剑指 Offer 05. 替换空格 请实现一个函数,把字符串 s 中的每个空格替换成"%20". 示例 1: 输入:s = "We are h ...

  6. 升级pip报错ERROR: Could not install packages due to an OSError: [WinError 5]

    今天在安装python第三方库时,提示pip需要升级,没有多想直接升级,结果报错: 1 ERROR: Could not install packages due to an OSError: [Wi ...

  7. 在Mac搭建一个便捷的Markdown创作环境

    前言 使用 Typora + PicGo + Gitee + Snipaste 在 Mac 搭建一个 Markdown 编辑环境. Typora 是一款简洁的 Markdown 编辑器: PicGo ...

  8. JsonCpp JSON格式处理库的介绍和使用(面向业务编程-文件格式处理)

    JsonCpp JSON格式处理库的介绍和使用(面向业务编程-文件格式处理) 介绍 JSON是一种轻量级的数据交换格式,它是一种键值对的集合.它的值可以是数字.字符串.布尔值.序列. 想知道更多有关J ...

  9. GitLab服务器傻瓜式搭建教程

    开始前的准备 需要有一台Linux系统的服务器或虚拟机 QAQ 安装包下载地址:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ 注* 本教程无需下载安装 ...

  10. kubernetes 安装 Prometheus + Grafana

    kubernetes 安装 Prometheus + Grafana kubernetes install Prometheus + Grafana 官网 Official website https ...