【问题标题】:Implementation of Thread-local storage (TLS) in C/C++ (multithreading)C/C++(多线程)中线程本地存储(TLS)的实现
【发布时间】:2014-06-01 01:38:04
【问题描述】:

我想了解Thread-local storage (TLS) 类型的实现。在C++11 作为thread_local 关键字或C 作为__thread 关键字可用。这篇wikipedia 文章说:

有时希望两个线程引用同一个 静态或全局变量实际上是指不同的内存 位置,从而使变量 thread-local 成为规范的 示例是 C 错误代码变量 errno

这用于将staticglobal 变量设置为线程本地,以便其他线程无法访问它们。

我的问题是这些变量如何存储在内存中以使其成为线程的本地变量?
毕竟这些本质上是全局/静态变量,是什么阻止其他线程访问它们?它们是否保存在一些特殊的数据段中

【问题讨论】:

    标签: c linux multithreading memory c++11


    【解决方案1】:

    TLS 在每个线程对象中实现为一个数据数组。每个线程对象都有自己的数组本地副本,并且每个数组的大小相同。当您将全局/静态变量声明为使用 TLS 时,它与这些数组的索引相关联(这就是编译器/操作系统知道要分配多少个数组插槽的方式)。因此,当您在运行时访问变量时,您实际上是在访问正在访问该变量的线程上下文的数据数组中的关联槽。

    TLS 可能是 C++11 中的一个新的原生特性,但它已经在各种 OS API 中提供了很长时间。

    TLS 在 Windows 上使用 Win32 API TlsAlloc()TlsGetValue()TlsSetValue()TlsFree() 函数实现。以下是其工作原理的概述:Thread Local Storage

    这里概述了 TLS 在 Linux 上的工作原理:ELF Handling For Thread-Local Storage

    【讨论】:

    • 真的是数组吗?如果不同的线程在不同的内核上运行,并且两个线程都尝试访问数组的元素,那么包含数组元素的缓存线不会在内核之间来回乒乓吗?
    • 它是每线程数组,而不是全局数组。一个线程不能访问另一个线程的数组,这就是它对每个线程本地的原因。每个线程上下文都有自己的数组副本。
    • linux 的实现是否相同?对不起,我应该提到我在问 linux。
    • 我用 TLS 的 Linux 文档链接更新了我的答案。
    • Ok.. 所以,每个线程都有一个数组的本地副本,这意味着如果index0 thread0 有一个TLS 变量var1,那么其他线程会有什么index0 他们的数组?同一变量var1 的副本?为什么它会跨线程复制,因为其他线程没有使用该变量?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    相关资源
    最近更新 更多