C++11 中的双重检查锁定模式?
C++11 的新机器模型允许多处理器系统可靠地工作。重组指令。
正如 Meyers 和 Alexandrescu 指出的那样,“简单的”双重检查锁定模式实现在 C++03 中并不安全,
Singleton* Singleton::instance() {
if (pInstance == 0) { // 1st test
Lock lock;
if (pInstance == 0) { // 2nd test
pInstance = new Singleton;
}
}
return pInstance;
}
他们在 他们的文章表明,无论您作为程序员,在 C++03 中,编译器有太多的自由度:允许以一种不确定最终只有一个 Singleton 实例的方式对指令重新排序
。
我现在的问题是:
- 新的 C++11 机器模型的限制/定义现在是否会限制指令序列,即上述代码始终可以与 C++11 编译器一起使用?
- 当使用新的库工具(而不是此处的模拟
Lock
)时,此单例模式的安全 C++11 实现现在看起来如何?
The new machine model of C++11 allows for multi-processor systems to work reliably, wrt. to reorganization of instructions.
As Meyers and Alexandrescu pointed out the "simple" Double-Checked Locking Pattern implementation is not safe in C++03
Singleton* Singleton::instance() {
if (pInstance == 0) { // 1st test
Lock lock;
if (pInstance == 0) { // 2nd test
pInstance = new Singleton;
}
}
return pInstance;
}
They showed in their article that no matter what you do as a programmer, in C++03 the compiler has too much freedom: It is allowed to reorder the instructions in a way that you can not be sure that you end up with only one instance of Singleton
.
My question is now:
- Do the restrictions/definitions of the new C++11 machine model now constrain the sequence of instructions, that the above code would always work with a C++11 compiler?
- How does a safe C++11-Implementation of this Singleton pattern now looks like, when using the new library facilities (instead of the mock
Lock
here)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果 pInstance 是常规指针,则代码存在潜在的数据竞争 - 对指针(或任何内置类型)的操作不能保证是原子的(编辑:或者很好) -ordered)
如果
pInstance
是一个std::atomic
并且Lock
内部使用一个std::mutex
来实现同步(例如,如果Lock
实际上是std::lock_guard
),代码应该没有数据竞争。请注意,您需要两者显式锁定和原子
pInstance
来实现正确的同步。If
pInstance
is a regular pointer, the code has a potential data race -- operations on pointers (or any builtin type, for that matter) are not guaranteed to be atomic (EDIT: or well-ordered)If
pInstance
is anstd::atomic<Singleton*>
andLock
internally uses anstd::mutex
to achieve synchronization (for example, ifLock
is actuallystd::lock_guard<std::mutex>
), the code should be data race free.Note that you need both explicit locking and an atomic
pInstance
to achieve proper synchronization.由于静态变量初始化现在保证是线程安全的,因此 Meyer 的单例应该是线程安全的。
现在你需要解决主要问题:你的代码中有一个单例。
编辑:基于我的评论:与其他实现相比,此实现有一个主要缺点。如果编译器不支持此功能会发生什么?编译器会吐出线程不安全代码,甚至不发出警告。如果编译器不支持新接口,其他带锁的解决方案甚至无法编译。这可能是不依赖此功能的一个很好的理由,即使对于单例以外的事情也是如此。
Since static variable initialization is now guaranteed to be threadsafe, the Meyer's singleton should be threadsafe.
Now you need to address the main problem: there is a Singleton in your code.
EDIT: based on my comment below: This implementation has a major drawback when compared to the others. What happens if the compiler doesn't support this feature? The compiler will spit out thread unsafe code without even issuing a warning. The other solutions with locks will not even compile if the compiler doesn't support the new interfaces. This might be a good reason not to rely on this feature, even for things other than singletons.
C++11 不会改变双重检查锁定实现的含义。如果你想进行双重检查锁定工作,你需要建立合适的内存屏障/栅栏。
C++11 doesn't change the meaning of that implementation of double-checked locking. If you want to make double-checked locking work you need to erect suitable memory barriers/fences.