c++ - thread_local 单例默认执行延迟初始化?

标签 c++ multithreading singleton

我有以下 thread_local 单例代码:

struct Singl {
  int& ref;

  Singl(int& r) : ref(r) {}
  ~Singl() {}

  void print() { std::cout << &ref << std::endl; }
};

static auto& singl(int& r) {
  static thread_local Singl i(r);
  return i;
}

int main() {
    int x = 4;
    singl(x).print();

    int y = 55;
    singl(y).print();

  return 0;
}

该程序打印两次对 x 的引用。

编译器( gcc 8.1 on godbolt )似乎对单例对象进行了延迟初始化:

singl(int&):
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     QWORD PTR [rbp-8], rdi
        mov     rax, QWORD PTR fs:0
        add     rax, OFFSET FLAT:guard variable for singl(int&)::i@tpoff
        movzx   eax, BYTE PTR [rax]
        test    al, al
        jne     .L5
        mov     rax, QWORD PTR [rbp-8]
        mov     rdx, QWORD PTR fs:0
        add     rdx, OFFSET FLAT:singl(int&)::i@tpoff
        mov     rsi, rax
        mov     rdi, rdx
        call    Singl::Singl(int&)
        mov     rax, QWORD PTR fs:0
        add     rax, OFFSET FLAT:guard variable for singl(int&)::i@tpoff
        mov     BYTE PTR [rax], 1
        mov     rax, QWORD PTR fs:0
        add     rax, OFFSET FLAT:singl(int&)::i@tpoff
        mov     edx, OFFSET FLAT:__dso_handle
        mov     rsi, rax
        mov     edi, OFFSET FLAT:_ZN5SinglD1Ev
        call    __cxa_thread_atexit
.L5:
        mov     rax, QWORD PTR fs:0
        add     rax, OFFSET FLAT:singl(int&)::i@tpoff
        leave
        ret

每当我多次调用传递不同参数的 singl 函数时,这是我可以预期的默认行为吗?或者是否有可能在后续调用中第二次初始化单例对象?

最佳答案

这确实是guaranteed 。当控制到达声明时,static/thread_local 局部变量只会初始化一次。

需要注意的几点:

  1. 如果多个线程同时调用该函数,则只有一个线程会执行初始化,其他线程将等待。这就是反汇编中的保护变量所做的事情。

  2. 如果初始化抛出异常,则视为不完整,并将在下次控制到达时再次执行。

换句话说,他们_只是工作_™。

关于c++ - thread_local 单例默认执行延迟初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51515329/

相关文章:

c++ - 在 SPOJ INCSEQ 中获取 WA - 增加子序列

c++结构和方法,未正确返回

c# - 无法将类型 'System.Threading.Tasks.Task' 隐式转换为 'Windows.Foundation.IAsyncAction' 。存在显式转换

java - 如何使用通过对象收集的数据填充 arrayList。 (安卓)

c# - 为什么单例不能直接实现 IObjectReference?

c++ - 获取 Unresolved external 错误

C++ std::string 数组到无符号 char 数组的转换

java.lang.Thread.State : BLOCKED on java. lang.Object

wpf - XAML 绑定(bind) BitmapImage ViewModel 属性

c# - 静态方法和变量中的线程安全