我刚刚阅读了优秀的博客 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 上完成对
已被刷新。然后线程 A 可以读取 pInstance
的写入(刷新到内存)的系统pInstance
,将指针视为非 null,并返回它可能允许线程 A 在线程 B 完成将其存储到内存之前访问 Singleton
。
第一次刷新是必要的,以确保Singleton
构造期间写入的刷新已完成在您尝试在不同的线程中使用它。 p>
根据您运行的硬件,这可能不是问题。
关于c++ - 在 C++ 中使用带内存屏障的双重检查锁定的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52981057/