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

时间:2018-10-25 03:47:37

标签: c++ singleton double-checked-locking

我刚刚阅读了出色的博客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;
    }

1 个答案:

答案 0 :(得分:0)

不,这不安全。阅读示例之前的三段以及之后的两段,潜在的问题是系统在pInstance构造完成之前已在线程B上完成了对Singleton的写操作(冲入内存)酡。然后线程A可以读取pInstance,将指针视为非空,然后返回该指针,从而可能允许线程A在线程B将其存储到内存中之前访问Singleton

必须首先进行刷新,以确保在构造Singleton之前完成写操作的刷新,然后再尝试在其他线程中使用它。

取决于您所运行的硬件,这可能不是问题。