C++11 中的双重检查锁定模式?

发布于 2024-11-07 04:32:23 字数 771 浏览 0 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

赠我空喜 2024-11-14 04:32:23

如果 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 an std::atomic<Singleton*> and Lock internally uses an std::mutex to achieve synchronization (for example, if Lock is actually std::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.

纸短情长 2024-11-14 04:32:23

由于静态变量初始化现在保证是线程安全的,因此 Meyer 的单例应该是线程安全的。

Singleton* Singleton::instance() {
  static Singleton _instance;
  return &_instance;
}

现在你需要解决主要问题:你的代码中有一个单例。

编辑:基于我的评论:与其他实现相比,此实现有一个主要缺点。如果编译器不支持此功能会发生什么?编译器会吐出线程不安全代码,甚至不发出警告。如果编译器不支持新接口,其他带锁的解决方案甚至无法编译。这可能是不依赖此功能的一个很好的理由,即使对于单例以外的事情也是如此。

Since static variable initialization is now guaranteed to be threadsafe, the Meyer's singleton should be threadsafe.

Singleton* Singleton::instance() {
  static Singleton _instance;
  return &_instance;
}

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.

睫毛溺水了 2024-11-14 04:32:23

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文