简体   繁体   English

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

[英]Thread-safe singleton in C++11

I know the following is a thread-safe way to implement a singleton in C++11: 我知道以下是在C ++ 11中实现单例的一种线程安全的方法:

Foo* getInst()
{
    static Foo* inst = new Foo(...);
    return inst;
}

I read in this answer that the following is also thread-safe: 我在这个答案中读到以下内容也是线程安全的:

Foo& getInst()
{
    static Foo inst(...);
    return inst;
}

Is it really thread-safe? 它真的是线程安全的吗?
Isn't it a problem that the instance of Foo will be allocated in a single stack frame will not be allocated on the heap? Foo的实例 分配到单个堆栈帧中 不会在堆上分配是不是一个问题?

If it is thread-safe, is there a strong reason to prefer one to the other? 如果它是线程安全的,是否有充分的理由选择一个到另一个?

Static variables are NOT allocated on the stack. 静态变量不在堆栈上分配。 In the first variant you have a static pointer (a global variable) initialized with a memory obtained from the heap, while in the second one you have whole static object. 在第一个变体中,您有一个静态指针(一个全局变量),它是用从堆中​​获取的内存初始化的,而在第二个变体中,您有一个完整的静态对象。

Both versions use internal compiler guards (namely __cxa_guard_acquire() and __cxa_guard_release() , which are functionally equivalent to mutex::lock() and mutex::unlock() ) to ensure serialized access to a special variable that tells whether or not your global instances are already initialized or not. 两个版本都使用内部编译器保护(即__cxa_guard_acquire()__cxa_guard_release() ,它们在功能上等同于mutex::lock()mutex::unlock() ),以确保对特殊变量的序列化访问,该变量告知您的全局实例已经初始化或未初始化。

Your code: 你的代码:

Foo& getInst()
{
    static Foo inst(...);
    return inst;
}

will actually look like that after the compilation: 编译后实际上看起来像这样:

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;
}

So both of your exampes are thread safe. 所以你的两个例子都是线程安全的。

inst in your example won't be allocated on stack. 你的例子中的inst不会在堆栈上分配。 It will be allocated somewhere in .data or .bss section. 它将在.data.bss部分的某处分配。 Otherwise this static variable couldn't live all the time program executes, and so it couldn't have the same value, which was before, each time you enter this function. 否则,这个静态变量无法在程序执行时始终存在,因此每次进入此函数时,它都不能具有相同的值。

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

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