繁体   English   中英

thread_local单例默认情况下执行延迟初始化?

[英]thread_local singleton performs lazy initialization by default?

我有以下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的引用打印两次。

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

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函数时,这是我可以期待的默认行为吗? 还是单例对象可能在随后的调用中第二次初始化?

确实可以保证 当控制到达声明时,static / thread_local局部变量仅初始化一次。

需要注意的几点:

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

  2. 如果初始化引发异常,则认为该异常未完成,并将在下次控制到达该异常时再次执行。

换句话说,它们只工作 ™。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM