加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C 11中的线程安全单例

发布时间:2020-12-16 10:35:10 所属栏目:百科 来源:网络整理
导读:我知道以下是在C 11中实现单例的一种线程安全的方法: Foo* getInst(){ static Foo* inst = new Foo(...); return inst;} 我在this answer中读到以下内容也是线程安全的: Foo getInst(){ static Foo inst(...); return inst;} 它真的是线程安全的吗? 将Foo
我知道以下是在C 11中实现单例的一种线程安全的方法:

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

我在this answer中读到以下内容也是线程安全的:

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

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

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

解决方法

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

两个版本都使用内部编译器保护(即__cxa_guard_acquire()和__cxa_guard_release(),它们在功能上等同于mutex :: lock()和mutex :: unlock())以确保对特殊变量的序列化访问,该变量告知您的全局实例已经初始化或未初始化.

你的代码:

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

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

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读