【发布时间】:2016-09-12 16:14:00
【问题描述】:
阅读 this 关于 C++ 中的双重检查锁定模式的文章,我到达了作者展示使用 volatile 变量“正确”实现 DCLP 的尝试之一的地方(第 10 页):
class Singleton {
public:
static volatile Singleton* volatile instance();
private:
static volatile Singleton* volatile pInstance;
};
// from the implementation file
volatile Singleton* volatile Singleton::pInstance = 0;
volatile Singleton* volatile Singleton::instance() {
if (pInstance == 0) {
Lock lock;
if (pInstance == 0) {
volatile Singleton* volatile temp = new Singleton;
pInstance = temp;
}
}
return pInstance;
}
在这样的例子之后有一个我不明白的文本sn-p:
首先,标准对可观察行为的限制仅适用于 标准定义的抽象机器,以及该抽象机器 没有多个执行线程的概念。结果,虽然 该标准防止编译器重新排序读取和写入 volatile data within 一个线程,它完全不施加任何约束 这样的重新排序跨线程。至少大多数编译器是这样的 实施者解释事物。因此,在实践中,许多 编译器可能会从上面的源代码生成线程不安全的代码。
及以后:
... C++ 的抽象机是单线程的,C++ 编译器可以 选择从上面的源代码生成线程不安全的代码, 无论如何。
这些说明与单处理器上的执行有关,因此绝对不是缓存一致性问题。
如果编译器无法对线程内中的易失性数据的读取和写入重新排序,那么对于此特定示例,它如何重新排序跨线程的读取和写入,从而生成线程- 不安全的代码?
【问题讨论】:
-
那篇文章是 2004 年的,因此比 C++11 及其更新的抽象机器早了很多年。
-
@molbdnilo 好的,但是如何解释编译器可以重新排序跨线程的读取和写入的语句?
标签: c++ multithreading singleton double-checked-locking