`
lxy2330
  • 浏览: 469247 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

线程局部存储Thread Local Storage-TLS(总结整理)

 
阅读更多


在线程的学习中我们知道每个线程除了共享进程的资源外还拥有各自的私有资源:  

一个寄存器组(或者说是线程上下文);一个专属的堆栈;一个专属的消息队列;一个专属的Thread Local Storage(TLS);一个专属的结构化异常处理串链。其中线程上下文在线程的学习中已经解释过了,堆栈没有什么好说的,消息队列会在USER 和GDI 子系统一节中讲解,那么这节的任务就是集中讲解线程局部存储Thread Local Storage(TLS);结构化异常处理Structured Exception Handling(SEH)会在后面的单独讲解。
 

TLS 是一个良好的Win32 特质,让多线程程序设计更容易一些。TLS 是一个机制,经由它,程序可以拥有全域变量,但处于「每一线程各不相同」的状态。也就是说,进程中的所有线程都可以拥有全域变量,但这些变量其实是特定对某个线程才有意义。例如,你可能有一个多线程程序,每一个线程都对不同的文件写文件(也因此它们使用不同的文件handle)。这种情况下,把每一个线程所使用的文件handle 储存在TLS 中,将会十分方便。当线程需要知道所使用的handle,它可以从TLS 获得。重点在于:线程用来取得文件handle 的那一段码在任何情况下都是相同的,而从TLS中取出的文件handle 却各不相同。非常灵巧,不是吗?有全域变数的便利,却又分属各线程。 


  虽然TLS 很方便,它并不是毫无限制。在Windows NT 和Windows 95 之中,有64 个DWORD slots 供每一个线程使用。这意思是一个进程最多可以有64 个「对各线程有不同意义」的DWORDs。 虽然TLS 可以存放单一数值如文件handle,更常的用途是放置指针,指向线程的私有资料。有许多情况,多线程程序需要储存一堆数据,而它们又都是与各线程相关。许多程序员对此的作法是把这些变量包装为C 结构,然后把结构指针储存在TLS 中。当新的线程诞生,程序就配置一些内存给该结构使用,并且把指针储存在为线程保留下来的TLS 中。一旦线程结束,程序代码就释放所有配置来的区块。既然每一个线程都有64 个slots 用来储存线程自己的数据,那么这些空间到底打哪儿来?在线程的学习中我们可以从结构TDB中看到,每一个thread database 都有64 个DWORDs 给TLS 使用。当你以TLS 函式设定或取出数据,事实上你真正面对的就是那64 DWORDs。好,现在我们知道了原来那些“对各线程有不同意义的全局变量”是存放在线程各自的TDB中阿。
 

    接下来你也许会问:我怎么存取这64个DWORDS呢?我又怎么知道哪个DWORDS被占用了,哪个没有被占用呢?首先我们要理解这样一个事实:系统之所以给我们提供TLS这一功能,就是为了方便的实现“对各线程有不同意义的全局变量”这一功能;既然要达到“全局变量”的效果,那么也就是说每个线程都要用到这个变量,既然这样那么我们就不需要对每个线程的那64个DWORDS的占用情况分别标记了,因为那64个DWORDS中的某一个一旦占用,是所有线程的那个DWORD都被占用了,于是KERNEL32 使用两个DWORDs(总共64 个位)来记录哪一个slot 是可用的、哪一个slot 已经被用。这两个DWORDs 可想象成为一个64 位数组,如果某个位设立,就表示它对应的TLS slot 已被使用。这64 位TLS slot 数组存放在process database 中(在进程一节中的PDB结构中我们列出了那两个DWORDs)。
 

下面的四个函数就是对TLS进行操作的:  

(1)TlsAlloc  

上面我们说过了KERNEL32 使用两个DWORDs(总共64 个位)来记录哪一个slot 是可用的、哪一个slot 已经被用。当你需要使用一个TLS slot 的时候,你就可以用这个函数将相应的TLS slot位置1。  

(2)TlsSetValue  

TlsSetValue 可以把数据放入先前配置到的TLS slot 中。两个参数分别是TLS slot 索引值以及欲写入的数据内容。TlsSetValue 就把你指定的数据放入64 DWORDs 所组成的数组(位于目前的thread database)的适当位置中。  

(3)TlsGetValue  

这个函数几乎是TlsSetValue 的一面镜子,最大的差异是它取出数据而非设定数据。和TlsSetValue 一样,这个函数也是先检查TLS 索引值合法与否。如果是,TlsGetValue 就使用这个索引值找到64 DWORDs 数组(位于thread database 中)的对应数据项,并将其内容传回。  

(4)TlsFree  

这个函数将TlsAlloc 和TlsSetValue 的努力全部抹消掉。TlsFree 先检验你交给它的索引值是否的确被配置过。如果是,它将对应的64 位TLS slots 位关闭。然后,为了避免那个已经不再合法的内容被使用,TlsFree 巡访进程中的每一个线程,把0 放到刚刚被释放的那个TLS slot 上头。于是呢,如果有某个TLS 索引后来又被重新配置,所有用到该索引的线程就保证会取回一个0 值,除非它们再调用TlsSetValue。
分享到:
评论

相关推荐

    [并发并行]_[C/C++]_[使用线程本地存储Thread Local Storage(TLS)调用复制文件接口的案例]

    【并发并行】_【C/C++]_【使用线程本地存储Thread Local Storage(TLS)调用复制文件接口的案例】 在多线程编程中,线程本地存储(Thread Local Storage,简称TLS)是一种用于存储线程私有数据的技术。每个线程都有...

    TLS_TEST.rar_TLS_Thread Local Storage

    描述中提到的“线程局部存储”(TLS,也常被误解为Thread Local Storage)是编程语言中一个重要的特性,特别是在多线程环境下。它允许每个线程拥有自己独立的变量副本,这些副本只对创建它们的线程可见,避免了在...

    TLS.rar_Thread Local Storage

    线程局部存储(thread-local storage, TLS)是一个使用很方便的存储线程局部数据的系统。利用TLS机制可以为进程中所有的线程关联若干个数据,各个线程通过由TLS分配的全局索引来访问与 自己关联的数据。这样,每个...

    线程局部存储机制总结

    线程局部存储(Thread Local Storage,简称TLS)是一种编程技术,允许程序为每个线程分配独立的内存空间。这些空间只对该线程可见,其他线程无法直接访问。这一特性在多线程环境中特别有用,因为它可以避免多个线程...

    thread-local-storage.pdf

    线程局部存储(Thread-Local Storage,TLS)是多线程编程中的一种技术,用于在每个线程中维护独立的数据副本,避免了数据共享带来的同步问题。在描述的文档"thread_local_storage.pdf"中,作者Ulrich Drepper探讨了...

    tls.rar_TLS_Thread Local Storage_thread local

    在IT领域,线程本地存储(TLS,Thread Local Storage)是一种编程技术,它允许程序为每个线程维护独立的数据副本。这种技术在多线程环境中非常有用,因为它避免了数据竞争,提高了并发性能,同时也提供了数据隔离。...

    Dynamic-TLS.rar_DynamicTLS_线程 TLS

    在Windows操作系统中,线程局部存储(Thread Local Storage,简称TLS)是一种高效且灵活的机制,它允许每个线程拥有自己的变量副本,而这些副本彼此独立,不会互相干扰。本文将深入探讨如何在Windows环境下使用动态...

    MFC.rar_MFC线程_线程局部存储

    在MFC中,线程是并发执行的程序实体,而线程局部存储(TLS, Thread Local Storage)则是一种特殊的数据存储机制,允许每个线程拥有独立的数据副本。 线程是操作系统分配CPU时间的基本单元,多个线程可以在同一进程...

    C++采用TLS线程局部存储的用法实例

    线程局部存储(TLS,Thread Local Storage)是C++中一种用于在线程间隔离数据的机制,它允许每个线程拥有自己独立的数据副本,而不会互相干扰。在多线程编程中,TLS常用于存储线程特有的数据,如线程ID、线程初始化...

    共享线程和局部存储技术

    线程局部存储(Thread Local Storage, TLS)是针对线程的一种存储机制,每个线程都有自己的独立存储区域,用于存放特定于该线程的数据。这样可以避免多线程环境中数据冲突的问题,同时也提供了线程间数据隔离,确保...

    tls线程本地存储例子

    标题中的“tls线程本地存储”指的是在编程中,特别是在多线程环境下,使用Thread Local Storage(TLS)来实现线程私有的数据存储。TLS允许每个线程拥有自己的变量副本,确保了数据的安全性和隔离性,避免了在多线程...

    test-tls.tar.gz

    glibc是GNU C库的简称,它是Linux和其他类UNIX系统中C语言编程的基础,提供了许多系统调用和常用函数的实现,包括TLS(Thread Local Storage)功能。TLS允许每个线程拥有自己的变量副本,而不是共享全局变量,从而...

    MFC局部线程存储

    在多线程编程中,局部线程存储(TLS,Thread Local Storage)是一种关键的概念,它允许每个线程拥有自己的变量副本,确保了数据的安全性和线程间隔离。 MFC中的局部线程存储主要通过`CWinThread`类以及相关的API...

    基于线程局部存储的内存管理模块,解决内存碎片,可直接用于工程

    线程局部存储(TLS,Thread Local Storage)是一种有效的优化策略,尤其是在多线程环境中,它可以为每个线程提供独立的数据存储,避免了线程间的数据冲突。在本项目中,作者设计了一个基于线程局部存储的内存管理...

    libevent-thread-20140224-1.7z

    1. **线程局部存储(Thread Local Storage)**:Libevent可能使用TLS来存储线程特有的数据,如事件基或配置信息,以避免在多线程环境中的冲突。 2. **回调函数的执行**:在多线程环境下,回调函数的执行需要确保...

    线程存储和共享内存

    线程局部存储(Thread Local Storage,TLS)则是针对线程的数据独立性提出的解决方案。与进程不同,线程是进程内的执行单元,它们共享进程的内存空间。但在某些情况下,我们也需要为线程维护私有数据,这就需要用到...

    Win32 多线程程序设计-线程完全手册--包括例程(Jim Beveridge&Roboert Wiener)

    这时,可以使用线程局部存储(Thread Local Storage, TLS),通过`TlsAlloc`分配TLS索引,然后用`TlsSetValue`和`TlsGetValue`设置和获取线程特定的值。 6. **线程生命周期管理**:线程创建后会自动运行,直到完成其...

    tls.rar_TLS

    在x86架构上实现TLS,开发者需要考虑线程局部存储模型,如IA-32的Thread Local Storage Index Register (TSR) 或x86_64的Thread Pointer (RTP)。TLS允许每个线程拥有自己的数据副本,而无需全局同步,这在多线程环境...

Global site tag (gtag.js) - Google Analytics