我刚刚阅读了出色的博客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;
}
答案 0 :(得分:0)
不,这不安全。阅读示例之前的三段以及之后的两段,潜在的问题是系统在pInstance
构造完成之前已在线程B上完成了对Singleton
的写操作(冲入内存)酡。然后线程A可以读取pInstance
,将指针视为非空,然后返回该指针,从而可能允许线程A在线程B将其存储到内存中之前访问Singleton
。
必须首先进行刷新,以确保在构造Singleton
之前完成写操作的刷新,然后再尝试在其他线程中使用它。
取决于您所运行的硬件,这可能不是问题。