【技术分享】线程本地存储(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. Nginx http 文件服务器 中文名称文件乱码以及不能访问下载问题 (解决全过程)

    书接上文: 在Windows 环境下使用 Nginx 搭建 HTTP文件服务器 实现文件下载 全步骤(详细) _ 发现的中文乱码问题,终于自己解决了! ^_^ Nginx http 文件服务器 中文名 ...

  2. SpringBoot笔记--自动配置(高级内容)(下集)

    案例需求 实现步骤: 具体的实现 1.引入Jedis依赖 2.提供Jedis的Bean 找到SpringBoot的执行文件,按住Ctrl键,进入SpringBootApplication注解,再进入E ...

  3. 第一章 1.1.1节 Kubeadm安装K8S高可用集群

    1.1 安装前必读 请不要使用带中文的服务器和克隆的虚拟机. 生产环境建议使用二进制的方式安装. 文档中的IP地址要更换成自己的IP地址,要谨记!!! 1.2 基本环境配置 kubeadm安装方式自1 ...

  4. GUI编程--1

    GUI编程--1 GUI是什么 (Graphical User Interface),即用户图形界面编程. 怎么玩 平时怎么运用 组件 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 1.简介 ...

  5. webgl 系列 —— 着色器语言

    其他章节请看: webgl 系列 着色器语言 本篇开始学习着色器语言 -- GLSL全称是 Graphics Library Shader Language (图形库着色器语言) GLSL 是一门独立 ...

  6. python3各数据类型的常用方法

    python3数据类型包括: 数字.字符串str.列表list.元组tuple.字典dict.集合set.布尔bool 1.字符串(str)-可变-用"".''定义 (1)uppe ...

  7. jquery中判断复选框有没有被选上

    页面部分: <input type="checkbox" id="cbx" /><label for="cbx">点 ...

  8. 一次线上OOM问题的个人复盘

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明. 上个月,我们一个java服务上线后,偶尔会发生内存OOM(Out Of Memory)问题,但由于OOM导致服务 ...

  9. [Git]git分支查询——图像化[转载]

    1 git reflog git reflog : 可查看所有分支的所有操作记录(含: commit / reset / merge / checkout等操作) 1-1 查看分支的所有变更记录(含: ...

  10. [Linux/Git]比较两份文件的差异

    Command vim -d fileA fileB 或 git diff <oldCommitId> <newCommitId> X Recommend Files Matc ...