可见性和排序之间有什么关系/区别?

3
据我所知,可见性(Visibility)涉及一个线程在什么条件下能够观察到/看到另一个线程对共享变量的更新。即使是单处理器系统也可能遇到可见性问题。 而顺序性(Ordering)则涉及一个线程按照什么顺序看到另一个CPU中运行的内存操作。单处理器系统不会遇到顺序性问题。 但有时候,所谓的顺序性问题可以用可见性的概念来解释。
//Thread1 runs
int data;
boolean ready;
void method1(){
  data=1;
  ready=true;
}

//Thread2 runs
void method2(){
  if(ready){
  System.out.print(data);
  }
}

如果上面程序的输出为"0"(而不是"1"), 我们可以说这是一个顺序问题(即重新排序)---写入到ready似乎在写入到data之前发生。 然而,我认为我们也可以将这个输出解释为可见性的结果:Thread2首先看到了Thread1对ready的更新,然后是data,可能是由于存储缓冲区刷新到CPU缓存所致。如果print(data)在Thread2看到data更新之前执行,那么我们就得到了输出"0"。 考虑到这一点,我只想知道可见性和顺序之间的区别/关系是什么?

看看Doug Lea关于同步和Java内存模型的这篇文章。它是一个很好的概述,涵盖了原子性、可见性以及各种可能与您预期不同的排序。这里还有另一篇来自同一作者的文章,讲解了JSR-133 - Java内存模型 - SubOptimal
我想再添加一个(因为我刚刚偶然发现了它)http://jpbempel.blogspot.fr/2013/05/volatile-and-memory-barriers.html - SubOptimal
谢谢@SubOptimal,你推荐的文章很好,我在提问之前已经阅读过了。 - user2351818
1个回答

1
是的,排序和可见性是相关问题。
- 可见性指的是一个线程是否能够看到另一个线程执行的内存写操作的结果。 - 排序指的是第二个线程看到的更新顺序是否与第一个线程写入的(程序)顺序相匹配。
Java 内存模型并不直接涉及写入的排序。任何关于顺序的限制都是由可见性规则引起的,这些规则在 JLS 中有详细说明。这包括使用 volatile 变量以有效地禁止重新排序的情况。
值得注意的是,从第二个线程的角度来看,写入的重新排序可以在 JLS 内存模型不要求可见性的任何时候发生。正确的同步将在同步点处保证可见性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接