13

我已经阅读了许多考虑线程安全双重检查锁定的问题(对于单例或惰性初始化)。在某些线程中,答案是模式完全被破坏,其他人提出了解决方案。

所以我的问题是:有没有办法在 C++ 中编写一个完全线程安全的双重检查锁定模式?如果是这样,它看起来如何。

如果这使事情变得更容易,我们可以假设 C++11。据我所知,C++11 改进了可以产生所需改进的内存模型。

我确实知道在 Java 中可以通过使仔细检查保护变量 volatile 来实现。由于 C++11 从 Java 中借用了大部分内存模型,所以我认为这是可能的,但是如何呢?

4

2 回答 2

18

只需对延迟初始化的 Singleton 使用静态局部变量,如下所示:

MySingleton* GetInstance() {
  static MySingleton instance;
  return &instance; 
}

(C++11) 标准已经保证静态变量以线程安全的方式进行初始化,并且看起来它的实现至少与您自己编写的任何东西一样健壮和高性能。

初始化的线程安全可以在 (C++11) 标准的 §6.7.4 中找到:

如果在变量初始化时控制同时进入声明,则并发执行将等待初始化完成。

于 2012-09-06T14:28:03.290 回答
3

由于您想查看有效的 DCLP C++11 实现,这里有一个。

该行为是完全线程安全的,并且与GetInstance()Grizzly 的答案相同。

std::mutex mtx;
std::atomic<MySingleton *> instance_p{nullptr};

MySingleton* GetInstance()
{
    auto *p = instance_p.load(std::memory_order_acquire);

    if (!p)
    {
        std::lock_guard<std::mutex> lck{mtx};

        p = instance_p.load(std::memory_order_relaxed);
        if (!p)
        {
            p = new MySingleton;
            instance_p.store(p, std::memory_order_release);
        }
    }

    return p;
}
于 2017-08-19T04:09:11.360 回答