考虑以下写入volatile
内存的序列,我摘自David Chisnall 在 InformIT 的文章“了解 C11 和 C++11 原子”:
volatile int a = 1;
volatile int b = 2;
a = 3;
我对 C++98 的理解是,根据 C++98 1.9,这些操作无法重新排序:
需要符合要求的实现来模拟(仅)抽象机的可观察行为,如下所述......抽象机的可观察行为是其对易失性数据的读取和写入序列以及对库 I/O 函数的调用
Chisnall 说,对订单保留的约束仅适用于单个变量,并写道,符合要求的实现可以生成执行此操作的代码:
a = 1;
a = 3;
b = 2;
或这个:
b = 2;
a = 1;
a = 3;
C++11 重复了 C++98 的措辞
需要符合要求的实现来模拟(仅)抽象机的可观察行为,如下所述。
但这是关于volatile
s (1.9/8) 的:
对 volatile 对象的访问严格按照抽象机的规则进行评估。
1.9/12 表示访问volatile
泛左值(包括变量a
、b
和c
以上)是一种副作用,而 1.9/14 表示一个完整表达式(例如,语句)中的副作用必须先于后面的副作用在同一个线程中的完整表达。这使我得出结论,Chisnall 显示的两个重新排序是无效的,因为它们不符合抽象机器规定的排序。
是我忽略了什么,还是 Chisnall 弄错了?
(请注意,这不是线程问题。问题是是否允许编译器重新排序对volatile
单个线程中不同变量的访问。)