在 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
构造期间写入的刷新已经完成 在您尝试在不同的线程中使用它之前。
根据您使用的硬件 运行 这可能不是问题。
刚看完这篇精彩的博文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
构造期间写入的刷新已经完成 在您尝试在不同的线程中使用它之前。
根据您使用的硬件 运行 这可能不是问题。