标签: thread-local-storage

线程本地单例

我想创建一个单例类,在每个使用它的线程中实例化一次.我想将实例指针存储在TLS插槽中.我已经提出了以下解决方案,但我不确定在涉及线程本地存储时是否对singelton工厂的多线程访问有任何特殊考虑.也许还有一个更好的解决方案来实现线程本地单例.

class ThreadLocalSingleton 
{
    static DWORD tlsIndex;
public:
    static ThreadLocalSingleton *getInstance()
    {
        ThreadLocalSingleton *instance = 
            static_cast<ThreadLocalSingleton*>(TlsGetValue(tlsIndex));
        if (!instance) {
            instance = new ThreadLocalSingleton();
            TlsSetValue(tlsIndex, instance);
        }
        return instance;
    }
};
DWORD ThreadLocalSingleton::tlsIndex = TlsAlloc();
Run Code Online (Sandbox Code Playgroud)

Tls*功能当然是win32特定的,但便携性不是这里的主要问题.您对其他平台的想法仍然很有价值.

主要编辑:我最初询问在这种情况下使用双重检查锁定.然而正如DavidK指出的那样,无论如何都要在每个线程的基础上创建单例.

剩下的两个问题是:

  1. 是否适合回复TlsGetValue/TlsSetValue以确保每个线程获得一个实例并且每个线程只创建一次实例?

  2. 是否可以注册一个回调,允许我在该线程完成时清理与特定线程关联的实例?

c++ winapi singleton multithreading thread-local-storage

4
推荐指数
1
解决办法
4537
查看次数

无论如何,是否可以在 Win32 API 中动态释放线程本地存储?

我需要在跨平台项目中使用线程本地存储。在 *IX 下,我使用 pthreads,并且由于作为第二个参数传递的漂亮的析构函数指针可以避免内存泄漏pthread_key_create,但在 Windows 中TlsAlloc没有这样的东西。我也找不到在线程退出时调用任何函数的一般位置(否则我会自制一些在退出时调用的函数指针列表)。

就目前情况而言,我基本上遇到了一种情况,为了实际使用线程本地存储,我需要在堆上分配自己的空间并将指针传递给TlsSetValue,但是如果线程退出......我无法确保内存被释放(除了有人在线程函数末尾显式调用TlsGetValueand delete/ free/ /etc 之外)。HeapFree

有谁知道更好的方法吗?

c++ ssl winapi thread-local-storage

4
推荐指数
1
解决办法
1953
查看次数

tomcat的ThreadLocalLeakPreventionListener到底做了什么?

org.apache.catalina.core.ThreadLocalLeakPreventionListener的文档说"LifecycleListener在停止Context时触发Executor池中线程的更新,以避免线程本地相关的内存泄漏."

它是如何完全阻止ThreadLocal内存泄漏的?它是否在上下文停止时显式调用ThreadLocal的remove()方法?

据我所知,ThreadLocal是作为哈希映射实现的.映射键是对ThreadLocal实例本身的引用.映射值是线程本地值.

java thread-local thread-local-storage

4
推荐指数
1
解决办法
2465
查看次数

gcc/ld:静态链接的ELF二进制文件中的重叠节(.tbss,.init_array)

我正在使用gcc版本4.8.2(Debian 4.8.2-21)在x86_64机器上的Debian 7系统上静态编译一个非常简单的hello-world单行程序:

gcc test.c -static -o test
Run Code Online (Sandbox Code Playgroud)

我得到一个可执行的ELF文件,其中包括以下部分:

[17] .tdata            PROGBITS         00000000006b4000  000b4000
     0000000000000020  0000000000000000 WAT       0     0     8
[18] .tbss             NOBITS           00000000006b4020  000b4020
     0000000000000030  0000000000000000 WAT       0     0     8
[19] .init_array       INIT_ARRAY       00000000006b4020  000b4020
     0000000000000010  0000000000000000  WA       0     0     8
[20] .fini_array       FINI_ARRAY       00000000006b4030  000b4030
     0000000000000010  0000000000000000  WA       0     0     8
[21] .jcr              PROGBITS         00000000006b4040  000b4040
     0000000000000008  0000000000000000  WA       0     0     8
[22] .data.rel.ro      PROGBITS         00000000006b4060  000b4060
     00000000000000e4  0000000000000000  WA       0     0     32
Run Code Online (Sandbox Code Playgroud)

注意,该.tbss部分分配在地址0x6b4020..0x6b4050(0x30字节),它与.init_array0x6b4020..0x6b4030(0x10字节) …

gcc elf ld static-linking thread-local-storage

4
推荐指数
1
解决办法
3134
查看次数

fs:0x30 在 Linux 中提供什么?

我试图理解atexit()函数的源代码,但我坚持这一点 (第 409 行〜第 415 行,PTR_DEMANGLE()

我可以理解内联汇编需要取得重大进展

xor    rdx,QWORD PTR fs:0x30
Run Code Online (Sandbox Code Playgroud)

但我真的不明白 fs:0x30 的含义是什么

所以我搜索了google但只得到了Windows上fs:0x30的含义,这与PEB相关

我还尝试搜索PTR_DEMANGLE()函数,并找到了这个,但没有帮助

这也给我提出了一个新问题:

比如说,我需要知道 fs:0xXX 的用法,这是很少使用的。我应该直接参考哪本手册?ELF标准文件?

顺便说一句,英语不是我的母语,这篇文章可能有一些语法或拼写错误,请原谅我,非常感谢!

assembly glibc reverse-engineering x86-64 thread-local-storage

4
推荐指数
1
解决办法
1181
查看次数

线程局部变量的初始化

我最近使用了一个对象,其目的是将内存作为单例进行分配和释放。就像是

class MyValue
{
  // ...

  static Allocator& GetAllocator()
  {
    static Allocator allocator;
    return allocator;
  }

  // ...
};
Run Code Online (Sandbox Code Playgroud)

后来我意识到它Allocator不是线程安全的:当多个线程同时使用同一个分配器时,偶尔会发生奇怪的事情,导致断言和分段错误。

解决方案:为不同的线程使用不同的分配器:

class MyValue
{
  // ...

  static Allocator& GetAllocator()
  {
    thread_local static Allocator allocator;
    return allocator;
  }

  // ...
};
Run Code Online (Sandbox Code Playgroud)

惊人的!我的问题都消失了!只有一个问题: 每次创建线程时我的分配器变量都会被初始化,即使大多数线程不会使用该变量?

分配器的初始化可能是繁重的操作,因此我希望仅在实际需要时才对其进行初始化,而不是在每个线程中进行初始化。

我读到thread_local变量是由每个线程分配的。这是否意味着它们也是被构建的?这种分配(或构造)是针对创建的每个线程系统地发生还是仅针对使用它的线程发生?

我依稀记得在课程中听说过有关线程和线程本地存储的大多数细节都依赖于平台。如果是这样的话,我对 Linux 和 FreeBSD 特别感兴趣。


相关(有趣的读物,但我在那里找不到答案):

c++ multithreading thread-local-storage c++11

3
推荐指数
1
解决办法
6023
查看次数

内联汇编中访问thread_local变量

我正在处理一些具有使用内联汇编的优化版本的C ++代码。优化版本显示的行为不是线程安全的,可以追溯到3个全局变量,可以从程序集内部进行广泛访问。

__attribute__ ((aligned (16))) unsigned int SHAVITE_MESS[16];
__attribute__ ((aligned (16))) thread_local unsigned char SHAVITE_PTXT[8*4];
__attribute__ ((aligned (16))) unsigned int SHAVITE_CNTS[4] = {0,0,0,0};
Run Code Online (Sandbox Code Playgroud)

...

asm ("movaps xmm0, SHAVITE_PTXT[rip]");
asm ("movaps xmm1, SHAVITE_PTXT[rip+16]");
asm ("movaps xmm3, SHAVITE_CNTS[rip]");
asm ("movaps xmm4, SHAVITE256_XOR2[rip]");
asm ("pxor   xmm2,  xmm2");
Run Code Online (Sandbox Code Playgroud)

我天真地认为解决此问题的最简单方法是使变量成为thread_local,但这会导致程序集中出现段错误-似乎程序集不知道变量是否是线程局部的?

我在一个小thread_local测试用例的汇编中进行了研究,以查看gcc如何处理它们,mov eax, DWORD PTR fs:num1@tpoff并尝试修改代码以执行相同的操作:

asm ("movaps xmm0, fs:SHAVITE_PTXT@tpoff");
asm ("movaps xmm1, fs:SHAVITE_PTXT@tpoff+16");
asm ("movaps xmm3, fs:SHAVITE_CNTS@tpoff");
asm ("movaps xmm4, fs:SHAVITE256_XOR2@tpoff");
asm ("pxor   xmm2,  xmm2");
Run Code Online (Sandbox Code Playgroud)

如果所有变量也都是thread_local,则该方法有效,它也与参考实现(非汇编)匹配,因此看起来可以成功工作。但是,这似乎是特定于CPU的,如果我看一下-m32我用get 进行编译的输出mov eax, DWORD PTR …

c++ x86 assembly gcc thread-local-storage

3
推荐指数
1
解决办法
194
查看次数

我应该在哪里使用“swapgs”指令

您好,我是一名内核学习者,对 swapgs 有一些疑问。

根据 AMD 的文档,它交换了gs.base隐藏寄存器和 KernelGSBase MSR。

此外,“gs:XXXX”的寻址计算为“gs.base + base + (scale*index) +位移”


现在我的第一个问题是:

  1. gs.base 是段寄存器的隐藏部分
  2. 位移是“gs:XXXX”的“XXXX”部分
  3. index 可能是 gs 中的选择器索引

那么我应该在哪里存储“基础”和“比例”?


此外,我应该在哪里使用它,我当前的项目将虚拟内存空间的上半部分作为内核,并且编译器通常不会添加“gs:XXXX”作为寻址引用。

所以,特别是,我应该在哪里使用swapgs指令。

assembly operating-system kernel x86-64 thread-local-storage

3
推荐指数
1
解决办法
548
查看次数

在clojure中线程局部变量

  1. 没有其他原因,我有很多其他自定义库,我已编写在1.1上运行.

我需要一种直接的方式来获得线程局部变量很多我看到的方法与这个版本的clojure不兼容.

在这个例子中看到

例如(thread-local(atom 0)))

(def ^ {:dynamic true} counter)

似乎不适合我

所以我只需指出正确的方向.

java multithreading clojure thread-local thread-local-storage

2
推荐指数
1
解决办法
909
查看次数

Go中全局线程本地存储的可行性和最佳实践

我是Golang的初学者,我想在Go中实现类似于Java中的映射诊断上下文(MDC)的东西,这是通过线程本地存储来实现的。但是,我发现很难在网上找到有关 Go 中全局线程本地存储的信息。

我有几个问题:

  • 是否可以为Go中的每个goroutine创建一种全局线程本地存储来存储数据和上下文?

  • 尝试实现全局线程局部存储是否被认为是 Go 中的反模式?

  • 是否建议通过在 Go 中实现全局线程本地存储来替代传递上下文的方式?

  • 假设您的选择是,您更喜欢使用传递上下文的方法,还是尝试实现线程本地存储来保存和管理上下文?

我找到了一些对此的参考,但我无法得出结论来决定是否实施它。

multithreading go mdc goroutine thread-local-storage

2
推荐指数
1
解决办法
284
查看次数