`
逆风的香1314
  • 浏览: 1416446 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

线程本地存储 (TLS)

阅读更多

线程本地存储 (TLS) 是一个方法,通过该方法,给定的多线程进程中的每个线程都可以分配存储线程特定数据的位置。通过 TLS API(TlsAlloc、TlsGetValue、TlsSetValue、TlsFree)方式支持动态绑定(运行时)的线程特定数据。除了现有的 API 实现,Win32 和 Visual C++ 编译器现在还支持静态绑定(加载时间)基于线程的数据。

TLS 的 API 实现

通过 Win32 API 层和编译器实现“线程本地存储”。有关详细信息,请参见 Win32 API 文档中的 TlsAlloc、TlsGetValue、TlsSetValue 和 TlsFree。

Visual C++ 编译器包括使线程本地存储操作更加自动化的关键字,而不是通过 API 层。将在下一节(TLS 的编译器实现)描述此语法。

TLS 的编译器实现

为了支持 TLS,已将新属性 thread 添加到了 C 和 C++ 语言,并由 Visual C++ 编译器支持。此属性是一个扩展存储类修饰符,如上一节中所述。使用 __declspec 关键字声明 thread 变量。例如,以下代码声明了一个整数线程局部变量,并用一个值对其进行初始化:

__declspec( thread ) int tls_i = 1;
<!---->
<!---->

声明静态绑定线程的本地对象和变量时必须遵守下列原则:

  • thread 属性只能应用于数据声明和定义。它不能用于函数声明或定义。例如,以下代码将生成一个编译器错误:
    #define Thread  __declspec( thread )
    Thread void func(); // This will generate an error.
  • 只能在具有 static 作用域的数据项上指定 thread 修饰符。包括全局数据对象(包括 staticextern)、本地静态对象和 C++ 类的静态数据成员。不可以用 thread 属性声明自动数据对象。以下代码将生成编译器错误:
    #define Thread  __declspec( thread )
    void func1()
    {
    Thread int tls_i; // This will generate an error.
    }

    int func2( Thread int tls_i ) // This will generate an error.
    {
    return tls_i;
    }
  • 线程本地对象的声明和定义必须全都指定 thread 属性。例如,以下代码将生成错误:
    #define Thread  __declspec( thread )
    extern int tls_i; // This will generate an error, since the
    int Thread tls_i; // declaration and definition differ.
  • thread 属性不能用作类型修饰符。例如,以下代码将生成一个编译器错误:
    char __declspec( thread ) *ch;        // Error
  • C++ 类不能使用 thread 属性。但是,可以使用 thread 属性将 C++ 类对象实例化。例如,以下代码将生成一个编译器错误:
    #define Thread  __declspec( thread )
    class Thread C // Error: classes cannot be declared Thread.
    {
    // Code
    };
    C CObject;

    因为允许使用 thread 属性的 C++ 对象的声明,因此下面两个示例在语义上是等效的:

    #define Thread  __declspec( thread )
    Thread class B
    {
    // Code
    } BObject; // OK--BObject is declared thread local.

    class B
    {
    // Code
    };
    Thread B BObject; // OK--BObject is declared thread local.
  • 不将线程本地对象的地址视为常数,并且涉及此类地址的任何表达式都不视为常数。在标准 C 中,这种作法的效果是禁止将线程本地变量的地址用作对象或指针的初始值设定项。例如,C 编译器将以下代码标记为错误:
    #define Thread  __declspec( thread )
    Thread int tls_i;
    int *p = &tls_i; //This will generate an error in C.

    但是,此限制不适用于 C++。因为 C++ 允许动态初始化所有对象,因此可以用使用线程本地变量地址的表达式初始化对象。实现此操作的方式与实现线程本地对象结构的方式相同。例如,以上显示的代码在作为 C++ 源文件编译时不会生成错误。请注意:只有在其中获取地址的线程仍然存在的情况下,线程本地变量的地址才有效。

  • 标准 C 允许使用涉及引用自身的表达式初始化对象或变量,但只适用于非静态作用域的对象。虽然 C++ 通常允许使用涉及引用自身的表达式动态初始化对象,但是这种类型的初始化不允许用于线程本地对象。例如:
    #define Thread  __declspec( thread )
    Thread int tls_i = tls_i; // Error in C and C++
    int j = j; // OK in C++, error in C
    Thread int tls_i = sizeof( tls_i ) // Legal in C and C++

    请注意:包含正在初始化的对象的 sizeof 表达式不建立对自身的引用且在 C 和 C++ 中都是合法的。

    C++ 不允许此类对线程数据的动态初始化,因为将来可能要对线程本地存储功能进行增强。

  • 如果 DLL 将任何非本地数据或对象声明为 __declspec(线程),动态加载该 DLL 时会导致保护错误。使用 LoadLibrary 加载所有 DLL 后,每当代码引用非本地 __declspec(线程)数据时,将导致系统故障。由于线程的全局变量空间是在运行时分配的,因此此空间的大小是以应用程序的需求和所有静态链接的 DLL 的需求相加为基础计算出来的。使用 LoadLibrary 时,无法扩展此空间以允许放置用 __declspec(线程)声明的线程本地变量。如果 DLL 可能是用 LoadLibrary 加载的,请在 DLL 中使用 TLS API(如 TlsAlloc)来分配 TLS。
评论

相关推荐

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

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

    tls线程本地存储例子

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

    Dynamic-TLS.rar_DynamicTLS_线程 TLS

    它提供了线程安全的本地存储解决方案,避免了同步开销,并允许程序根据需求动态管理存储。通过理解并正确使用动态TLS,开发者可以编写出更加高效、健壮的多线程应用程序。在实际开发中,应充分考虑其特性,合理利用...

    线程局部存储机制总结

    - `DWORD m_tlsIndex`:系统级线程本地存储的索引,用来标识每个线程的存储空间。 #### 四、线程局部存储的工作原理 在MFC中,每个线程通过`CThreadSlotData`类的实例管理自己的线程局部存储空间。`...

    Swift中类型安全的线程本地存储-Swift开发

    线程本地存储(TLS)使您可以定义一个变量,每个变量Threadly是一个Swift µframework,可进行类型安全的线程本地存储。 什么是线程本地存储? 线程本地存储(TLS)使您可以定义一个变量,每个线程都有其自己的单独...

    关于Linux线程的线程栈以及TLS

    本文描述LinuxNPTL的线程栈简要实现以及线程本地存储的原理,实验环境中Linux内核版本为2.6.32,glibc版本是2.12.1,Linux发行版为ubuntu,硬件平台为x86的32位系统。b.对于LinuxNPTL线程,有很多话题。本文挑选了...

    逆向工程权威指南.下册

    涉及X86/X64、ARM/ARM-64、MIPS、Java/JVM等重要话题,详细解析了Oracle RDBMS、Itanium、软件狗、LD_PRELOAD、栈溢出、ELF、Win32 PE文件格式、x86-64(第、critical sections、syscalls、线程本地存储TLS、地址...

    sakeInject:Windows PE - CC++ 中的 TLS(线程本地存储)注入器

    标题 "sakeInject:Windows PE - CC++ 中的 TLS(线程本地存储)注入器" 指涉的是一个特定的软件开发工具或技术,它主要用于Windows可执行文件(PE,Portable Executable)中实现TLS(线程局部存储,Thread Local ...

    逆向工程权威指南

    涉及X86/X64、ARM/ARM-64、MIPS、Java/JVM等重要话题,详细解析了Oracle RDBMS、Itanium、软件狗、LD_PRELOAD、栈溢出、ELF、Win32 PE文件格式、x86-64(第、critical sections、syscalls、线程本地存储TLS、地址...

    android TLS

    例如,我们可以存储一些线程局部的缓存、线程本地的日志标识符,或者特定线程的调试信息。 TSD(Thread Specific Data)是TLS的另一种称呼,它们是同义的。在Android的JNI上下文中,使用pthread库的TSD功能,开发者...

    tls.rar_TLS_Thread Local Storage_thread local

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

    tls_src.zip_TLS

    线程本地存储(TLS,Thread Local Storage)是编程中一种重要的多线程同步机制,它为每个线程分配独立的数据存储区域,确保每个线程只能访问到属于自己的数据,而不会干扰其他线程。TLS在多线程编程中起到关键作用,...

    MFC线程处理概述.doc

    CWinThread类是MFC中处理线程的核心,它利用线程本地存储(TLS,Thread Local Storage)来维护每个线程特有的上下文信息。用户可以直接实例化CWinThread对象,但通常推荐使用MFC提供的全局函数AfxBeginThread来创建...

    Windows 内核情景分析--采用开源代码ReactOS (上册) part01

    5.11 线程本地存储TLS 421 5.12 进程挂靠 434 5.13 Windows的跨进程操作 442 5.14 Windows线程间的相互作用 450 第6章 进程间通信 467 6.1 概述 467 6.2 共享内存区(Section).. 469 6.3 线程的等待/唤醒...

    caffe多线程运行速度案例分析.docx

    **线程本地存储(TLS)**是指一种为每个线程提供独立存储空间的技术。对于Caffe而言,`CaffeContext`作为TLS变量,只支持本线程内的存储和访问。当`Classifier`对象在主线程中构造时,它所依赖的`CaffeContext`也同样...

Global site tag (gtag.js) - Google Analytics