c++ - thread_local 变量的实例是否保证由访问它们的线程初始化?

标签 c++ multithreading c++17 language-lawyer c++20

“所有具有线程局部存储持续时间的非局部变量都作为线程启动的一部分进行初始化,在线程函数开始执行之前进行排序。” ( https://en.cppreference.com/w/cpp/language/initialization )
但是, cppreference 似乎没有提到这些变量实际上是由正在启动的线程还是由正在启动新线程的线程初始化的。
考虑以下示例:
(id.hpp)

#include<thread>
extern thread_local const std::thread::id this_thread_id;
(id.cpp)
#include "id.hpp"
thread_local const std::thread::id this_thread_id = std::this_thread::get_id();
如果我访问 this_thread_id从一个不是主线程的线程中,我会得到那个线程的 id 吗?如 this_thread_id被初始化为“作为线程启动的一部分”,它也可能由原始调用线程初始化,因此 this_thread_id会有不正确的值。
我知道有一些设计模式可以完全避免这个问题,但这违背了这个问题的全部意义,所以我不想在这里使用它们。

最佳答案

作为本地线程,每个线程都会有一个拷贝,因此每个线程中都会有不同的值。
至于什么时候初始化:

is sequenced before the first statement of the initial function of a thread or is deferred. If it is deferred, the initialization associated with the entity for thread t is sequenced before the first non-initialization odr-use by t of any non-inline variable with thread storage duration defined in the same translation unit as the variable to be initialized


所以它在每个线程中被初始化,无论是在运行线程函数之前还是在使用之前。
我编写了一个测试:
#include <thread>
#include <iostream>

namespace m {
    std::thread::id get_id () {
        std::cout << "My get id called." << std::endl;
        return std::this_thread::get_id();
    }
}

thread_local const std::thread::id this_thread_id = m::get_id();

int main ()
{
    std::cout << "Main: " << this_thread_id << std::endl;
    
    std::thread th2 (
        [&]{
            uint64_t i {0};
            std::cout << "Thread.int: " << i << std::endl;
            std::cout << "Here it could be uninitialized." << std::endl;
            std::cout << "Thread .2: " << this_thread_id << std::endl;
        });

    th2.join ();
    
    std::cout << "End" << std::endl;
    
    return 0;
}
这是输出:
manuel@desktop:~/projects/soanswers/src (master)$ g++ ini.cc -o ini -std=c++2a -pthread && ./ini
Main: My get id called.
140064769697600
Thread.int: 0
Here it could be uninitialized.
Thread .2: My get id called.
140064769693440
End
所以它似乎在 g++它在第一次使用时被初始化。即使您只访问它所在的内存。

关于c++ - thread_local 变量的实例是否保证由访问它们的线程初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65521829/

相关文章:

c++ - 混合全局函数和类成员函数 C++

python - 在 Linux 中使用 SWIG for Python 转换字符串

Python多线程和HTTP请求

C++ - 指向shared_ptr的原始指针

c++ - 什么是无锁多线程编程?

c - 在 2 个 C 程序之间传输数据的最简单方法?

multithreading - 使用 applescriptobjc 实现 GDC

c++ - 是否允许编译器支持标准中已删除的功能?

c++ - 为什么 return SFINAE 转换运算符不起作用?