thread_local 变量何时以及如何进行初始化和销毁?

4

在我使用 thread_local 之前,我希望更好地理解它。

假设我声明:

thread_local myclass value;

这将为每个使用value的线程创建一个myclass的新实例。当线程退出时会发生什么?实例会被释放还是将继续留在内存中?析构函数何时调用?

thread_local是否锁定构造函数,以便只能在任何时刻调用一个构造函数?

2个回答

8

[basic.stc.thread]/1 使用thread_local关键字声明的所有变量都具有线程存储期。这些实体的存储将持续到创建它们的线程结束为止。每个线程都有一个独特的对象或引用,并且使用声明的名称引用与当前线程相关联的实体。

[basic.stc.thread]/2 具有线程存储期的变量在其首次odr-use(6.2)之前必须进行初始化,并且如果被构造,则应在线程退出时销毁。

不,构造函数调用没有自动同步。并不需要同步,因为只有一个线程可以尝试构造给定的线程本地对象。


假设我声明了一个随机数生成器 thread_local,并且它的种子来自时间。如果初始化没有同步,对于这种情况,我们可能会有几个随机数生成器返回相同的数字序列。 - Arsen Zahray
2
即使初始化是同步的(虽然它并不是,但让我们假装它是),这种情况仍可能发生。所需的只是在同一秒内发生两个调用。如果这在您的程序中是一个问题,您需要安排更好的种子生成机制;线程同步与此问题无关。 - Igor Tandetnik
1
通常可以使用 random_device 来初始化您的伪随机数生成器:thread_local std::mt19937 prng(std::random_device{}()); - Ted Lyngmo

4
根据此存储持续时间参考,thread_local变量:

... 在线程开始时分配,在线程结束时释放。

因此,是的,当线程结束时,该线程的thread_local变量的生命周期也会结束,这意味着那些特定实例将被销毁。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接