不知何故,CPU决定先写入x,然后再读取x。这个例子所说的就是这是有效的行为,或多或少地,这是被接受为有效行为的异常情况。
英特尔Itanium CPU可以产生这样的行为。
因此,与其:
//Thread 1
int x = 0;
int r1 = x;
x = 1;
//Thread 2
int x = 0;
int r2 = x;
x = 2;
//Thread 1
int x = 0;
x = 2; //from Thread 2
int r1 = x;
//Thread 2
int x = 0;
x = 1; //from Thread 1
int r2 = x;
这是完全有效的。(被接受的例外。)
r1 == 2
和 r2 == 1
。您的示例显示 r1 == 1
和 r2 == 2
,而“编译器不会重新排序每个线程中的语句; [...]”。 - akuzminykhr1
和r2
不是“内存位置”,或者至少没有其他线程引用它们。在CPU术语中,它们是寄存器,这就是为什么它们有像r1
这样的名称。半相关:https://preshing.com/20120515/memory-reordering-caught-in-the-act/,但那是关于StoreLoad重新排序,而不是必要的LoadStore重新排序,以创建所询问的条件。(除了这是对同一内存位置上的操作重新排序,这是不寻常的。) - Peter Cordesr1
和r2
将是Java堆栈上的数据。是的,要查看从共享内存加载的内容,您需要稍后将这些加载结果复制到可以收集它们的地方(例如内存中的本地变量),就像汇编版本的litmus测试中的CPU寄存器一样。 (CPU寄存器对于每个核心都是私有的。它们仅在存储数据并且物理上由SRAM制成(除了寄存器重命名之外),它们不具有通常意义上的地址,并且不能间接寻址。) - Peter Cordes