3

我正在阅读文章“ C++ and the Perils of Double-Checked Locking ”,它解释了 DCLP 中的问题。

文章的第二部分(链接转发)展示了如何尝试仅使用 C/C++ volatile 解决 DCLP(据我所知,这是不可能的)。在文章中,作者解释了如何做到这一点(最后一个例子是 11 号),但他们写道:

不幸的是,这一切都无助于解决第一个问题——C++ 的抽象机器是单线程的,而且 C++ 编译器可能会选择从刚才提到的源代码生成线程不安全的代码,无论如何。否则,失去优化机会会导致效率损失过大。毕竟这一切,我们回到第一方。但是等等,还有更多——更多的处理器。

这意味着(如果我理解正确的话),无论我们将如何使用 volatile,它都不会起作用,因为“ C++ 的抽象机器是单线程的,C++ 编译器可能会选择从源代码生成线程不安全的代码,例如刚才提到的

但这意味着“C++ 的抽象机器是单线程的”是什么意思?!

为什么上面所有这些挥发物的例子都不会阻止重新排序?

谢谢!

4

2 回答 2

2

从 C++11 开始,您的粗体标记句子不再正确。

过去
的含义:操作系统/设备可能支持多个线程,包括启动它们
的函数等。另一方面,C++ 编译器等“考虑”单线程环境,并且不知道使用多个线程时可能出现的问题线程。线程启动只是对它们的正常函数调用,并且操作系统对进程做了一些奇怪的事情,因为该调用既不知道也不有趣。

只要重新排序的代码部分相互独立,就可以在单线程环境中重新排序代码(例如,变量的写入/读取顺序使使用此变量的代码依赖于)。在多线程环境中,编译器不可能知道一个变量是否以及何时受到另一个线程的影响......

现在,在 C++11/C++14 中,
为防止优化破坏线程代码提供了独立于操作系统的支持。

于 2015-06-13T10:46:14.693 回答
0

这意味着一个线程执行的写入总是立即对其自身可见,并且将具有相同的逻辑结果,就好像代码没有被编译器或 CPU 重新排序一样,即使这可能已经发生了。

被破坏的是这些写入如何出现在共享相同数据空间的其他线程中。这是在 C++11 中修复的。

它还赋予了 const 和 mutable 稍微不同的含义。使类成员可变不再是过去的麻烦,现在可以在可以以线程安全方式修改成员时使用它,即任何更改都以逻辑一致的方式对其他线程可见。例如,使 std::mutex 或 std::atomic 可变完全没问题,但不是普通的 int。

于 2015-06-13T11:13:47.567 回答