c++ - 单例中静态声明之间的差异

标签 c++ multithreading design-patterns singleton

(代码取自书籍: http://gameprogrammingpatterns.com/ 作者:Robert Nystrom)

在上面的书中,作者提供了两种不同的创建单例类的方法:

第一个:

class FileSystem
{
public:
  static FileSystem& instance()
  {
    // Lazy initialize.
    if (instance_ == NULL) instance_ = new FileSystem();
    return *instance_;
  }

private:
  FileSystem() {}

  static FileSystem* instance_;
};

第二个:

class FileSystem
{
public:
  static FileSystem& instance()
  {
    static FileSystem *instance = new FileSystem();
    return *instance;
  }

private:
  FileSystem() {}
};

后来他指出第二个是更正确的方法,因为它是线程安全的,而第一个则不是。
是什么使第二个线程安全?
这两者之间的静态声明有什么区别?

最佳答案

第一个版本不是线程安全的,因为多个线程可能会尝试在没有任何同步的情况下同时读取和修改 instance_,这会导致竞争条件。

自 C++11 起,第二个版本是线程安全的。引用自cppreference (静态局部变量部分):

If multiple threads attempt to initialize the same static local variable concurrently, the initialization occurs exactly once (similar behavior can be obtained for arbitrary functions with std::call_once)

有了这个保证,对实例的修改只会发生一次,并且并发读取没有问题。

不过,在 C++11 之前,第二个版本并不是线程安全的。

关于c++ - 单例中静态声明之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29728910/

相关文章:

c++ - 类和指针,它们是如何工作的?

python - 更新传递给线程python的变量

c++ - OpenMP 线程数问题

java - 了解 GC 日志 - 应用程序线程已停止

javascript - 如何将 Mixins 用于每种类型的继承?

c++ - 无法在 C++ 中的数组中存储值

c++ - 一个类需要另一个类,另一个类需要第一个类。我怎么做?

c++ - COM 和 MSXML 的问题(仅限 64 位)

java - SimpleFactory、FactoryMethod、抽象工厂(实体示例)

java - 为具有不同参数的方法设计接口(interface)