对可变对象使用 volatile 关键字 [英] Using volatile keyword with mutable object
问题描述
在 Java 中,我知道 volatile
关键字提供了对变量的可见性.问题是,如果变量是对可变对象的引用,volatile
是否也提供对该对象内部成员的可见性?
In Java, I understand that volatile
keyword provides visibility to variables. The question is, if a variable is a reference to a mutable object, does volatile
also provide visibility to the members inside that object?
在下面的示例中,如果多个线程正在访问 volatile Mutable m
并更改 value
,它是否正常工作?
In the example below, does it work correctly if multiple threads are accessing volatile Mutable m
and changing the value
?
示例
class Mutable {
private int value;
public int get()
{
return a;
}
public int set(int value)
{
this.value = value;
}
}
class Test {
public volatile Mutable m;
}
推荐答案
这是对 volatile 的一些细节的旁注解释.写在这里是因为评论太多了.我想举一些例子来说明 volatile 如何影响可见性,以及它在 jdk 1.5 中是如何改变的.
This is sort of a side note explanation on some of the details of volatile. Writing this here because it is too much for an comment. I want to give some examples which show how volatile affects visibility, and how that changed in jdk 1.5.
给定以下示例代码:
public class MyClass
{
private int _n;
private volatile int _volN;
public void setN(int i) {
_n = i;
}
public void setVolN(int i) {
_volN = i;
}
public int getN() {
return _n;
}
public int getVolN() {
return _volN;
}
public static void main() {
final MyClass mc = new MyClass();
Thread t1 = new Thread() {
public void run() {
mc.setN(5);
mc.setVolN(5);
}
};
Thread t2 = new Thread() {
public void run() {
int volN = mc.getVolN();
int n = mc.getN();
System.out.println("Read: " + volN + ", " + n);
}
};
t1.start();
t2.start();
}
}
此测试代码的行为在 jdk1.5+ 中定义良好,但在 jdk1.5 之前没有定义良好.
The behavior of this test code is well defined in jdk1.5+, but is not well defined pre-jdk1.5.
在 jdk1.5 之前的世界中,易失性访问和非易失性访问之间没有明确的关系.因此,该程序的输出可能是:
In the pre-jdk1.5 world, there was no defined relationship between volatile accesses and non-volatile accesses. therefore, the output of this program could be:
- 读取:0, 0
- 读取:0、5
- 读取:5, 0
- 阅读:5、5
在 jdk1.5+ 世界中,volatile 的语义发生了变化,因此 volatile 访问影响非 volatile 访问的方式与同步完全相同.因此,在 jdk1.5+ 世界中只有某些输出是可能的:
In the jdk1.5+ world, the semantics of volatile were changed so that volatile accesses affect non-volatile accesses in exactly the same way as synchronization. therefore, only certain outputs are possible in the jdk1.5+ world:
- 读取:0, 0
- 读取:0、5
- 读取:5, 0 <- 不可能
- 阅读:5、5
输出 3. 是不可能的,因为从 volatile _volN 读取5"在 2 个线程之间建立了一个同步点,这意味着在分配给 _volN 之前从 t1 采取的所有操作必须对 t2 可见.
Output 3. is not possible because the reading of "5" from the volatile _volN establishes a synchronization point between the 2 threads, which means all actions from t1 taken before the assignment to _volN must be visible to t2.
进一步阅读:
这篇关于对可变对象使用 volatile 关键字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!