C++ 11中的线程安全单例

Kav*_*veh 3 c++ multithreading gcc thread-safety c++11

我知道以下是在C++ 11中实现单例的一种线程安全的方法:

Foo* getInst()
{
    static Foo* inst = new Foo(...);
    return inst;
}
Run Code Online (Sandbox Code Playgroud)

我在这个答案中读到以下内容也是线程安全的:

Foo& getInst()
{
    static Foo inst(...);
    return inst;
}
Run Code Online (Sandbox Code Playgroud)

它真的是线程安全的吗?
Foo的实例分配到单个堆栈帧中不会在堆上分配是不是一个问题?

如果它是线程安全的,是否有充分的理由选择一个到另一个?

Fre*_*pin 9

静态变量不是在堆栈上分配.在第一个变体中,您有一个静态指针(一个全局变量),它是用从堆中​​获取的内存初始化的,而在第二个变体中,您有一个完整的静态对象.

这两个版本使用编译器内部警卫(即__cxa_guard_acquire()__cxa_guard_release(),在功能上等同于mutex::lock()mutex::unlock()),以确保以一个特殊的变量,它告诉你的全局实例是否已经被初始化或没有序列号的访问.

你的代码:

Foo& getInst()
{
    static Foo inst(...);
    return inst;
}
Run Code Online (Sandbox Code Playgroud)

编译后实际上看起来像这样:

Foo& getInst()
{
    static Foo inst; // uninitialized - zero
    static guard instGuard; // zero

    if (is_initialized(instGuard) == false)
    {
        __cxa_guard_acquire(instGuard);
        // do the initialization here - calls Foo constructor
        set_initialized(instGuard);
        __cxa_guard_release(instGuard);
    }

    return inst;
}
Run Code Online (Sandbox Code Playgroud)

所以你的两个例子都是线程安全的.