首页 > 解决方案 > 动态加载库中的 thread_local 静态变量——它们是什么时候创建的?

问题描述

cppreferencethread_local在变量上声明了以下内容

对象的存储在线程开始时分配,在线程结束时释放。每个线程都有自己的对象实例。只有声明为 thread_local 的对象具有此存储持续时间。

我想使用在运行时通过/thread_local static加载的共享库中声明的成员变量。由于完全有可能在加载该库的时间点已经有相当多的线程在运行,其中一些线程稍后将访问该变量,我想知道如果在线程开始时分配存储空间,这是如何工作的?如果在创建线程的时间点程序中不存在该变量,这显然不能像那里解释的那样工作。此外,如果运行例如 100 个线程的进程会为每个线程创建该线程局部变量的实例,而其中只有少数线程实际访问该变量,这似乎是一种资源浪费。dlopenLoadLibrary

那么,这里的文档是不正确的,还是我在这里尝试的可能会导致未定义的行为?如果文档完全不正确,我在哪里可以找到关于现实中可以预期的可靠描述?如果它是定义的实现,我对 clang 如何在 macOS 和 Windows 上处理它特别感兴趣。

标签: c++dynamic-loadingthread-local-storage

解决方案


cppreference 所说的是意译。标准中的实际内容是

thread_local使用关键字声明的所有变量都有线程存储持续时间。这些实体的存储将持续到创建它们的线程的持续时间。每个线程都有一个不同的对象或引用,使用声明的名称是指与当前线程关联的实体。

那里没有关于何时分配存储的确切信息,只是它在线程期间持续存在。这意味着它可以在创建线程时分配,或者在第一次使用变量时分配,或者可能是两者的组合。

分配存储时,可能不会构造变量(我假设这就是您说“创建实例”时的意思)。这取决于变量的定义位置和方式。但是,如果它被构造,它不会被销毁,直到线程结束。

支持通过dlopen或者LoadLibrary是编译器/平台扩展来动态加载库,而不是语言的一部分。如何与之交互thread_local也将是特定于平台的。


推荐阅读