5

在阅读了一堆关于这个主题的问题/文章之后,我还有一件事不清楚。

据我了解(如果我错了,请纠正我)是变量的值可以在本地缓存到线程,因此如果一个线程更新该变量的值,则此更改可能对另一个线程不可见。then的使用volatile本质上是强制所有线程从同一位置读取变量的值。此外,有关该主题的所有文献都指出,对该变量进行同步将具有相同的效果。

我的问题是,我读过的任何内容都没有明确指出在不同变量上同步会导致相同的行为,但经常提供代码示例说明在以下两种情况下,从变量中读取的值将是最新的:

volatile int x;
...
int y = x;

final Object lock = new Object();
int x;
...
synchronized(lock) {
    int y = x;
}

那么问题来了:对任意变量进行同步是否会强制同步块中的每个变量访问都访问该变量的最新值?

4

2 回答 2

5

是不是在任何变量上同步都会强制同步块中的每个变量访问都访问该变量的最新值?

只要该变量的写入是在同一个变量的同步下完成的,您就可以对任何变量进行同步以进行读取。

在您的示例中,只要发生以下情况,那么在写入之前发生的所有写入都x将在后续读取之后可见:

synchronized(lock){
   x = 10;
}

所以对于你之前的观点:

...我读过的任何内容都没有明确指出在不同的变量上同步会导致相同的行为...

那是因为它不提供相同的行为。发生之前的关系在少数情况下发生,在您的情况下有两个重要的情况是

  1. 写入和随后读取相同的 volatile 变量
  2. 同一对象上监视器的退出和随后进入
于 2013-09-26T14:16:33.973 回答
2

这里有一篇启发性的文章提到它:

在 Java 内存模型中,volatile 字段在写入之后插入了存储屏障,在读取之前插入了加载屏障。...

请注意,没有什么特定于正在访问的字段。这意味着访问任何volatile 字段都会为所有缓存的变量生成屏障。

同步具有类似的功能。

于 2013-09-26T14:31:12.390 回答