在 C++ 中使用带内存屏障的双重检查锁定的正确方法是什么?

What the correct way when use Double-Checked Locking with memory barrier in c++?

刚看完这篇精彩的博文C++ and the Perils of Double-Checked Locking

而且我不明白为什么我们必须在示例 12 中使用第一个内存屏障(如下所示):

Singleton* Singleton::instance () {
       Singleton* tmp = pInstance;
       ... // insert memory barrier
       if (tmp == 0) {
          Lock lock;
          tmp = pInstance;
          if (tmp == 0) {
             tmp = new Singleton;
             ... // insert memory barrier
             pInstance = tmp;
          }
       }
       return tmp;
    }

改成下面的代码安全吗?为什么不呢?

Singleton* Singleton::instance () {
       if (pInstance == 0) {
          Lock lock;
          if (pInstance == 0) {
             Singleton* tmp = new Singleton;
             ... // insert memory barrier
             pInstance = tmp;
          }
       }
       return pInstance;
    }

不,这不安全。阅读示例前的三段和示例后的两段,潜在的问题是在 Singleton 的构造之前在线程 B 上完成写入 pInstance(刷新到内存)的系统酡。然后线程 A 可以读取 pInstance,将指针视为非空,并且 return 它可能允许线程 A 在线程 B 完成将其存储到内存之前访问 Singleton

第一次刷新是必要的,以确保 Singleton 构造期间写入的刷新已经完成 在您尝试在不同的线程中使用它之前

根据您使用的硬件 运行 这可能不是问题。