我读到java volatile是顺序一致但不是原子的。 对于atomicity,java提供了不同的库。
有人可以用简单的英语解释两者之间的区别吗?
(我相信问题范围包括C / C ++,因此添加这些语言标签以吸引更多观众。)
答案 0 :(得分:7)
想象一下这两个变量:
int i = 0;
volatile int v = 0;
这两种方法
void write() {
i = 5;
v = 2;
}
void read() {
if (v == 2) { System.out.println(i); }
}
volatile语义保证read
将打印5或不打印(假设当然没有其他方法正在修改字段)。如果v
不易变,read
也可能会打印0,因为i = 5
和v = 2
可能已经重新排序。我想这就是顺序一致性的意思,它具有更广泛的含义。
另一方面,挥发性不保证原子性。因此,如果两个线程同时调用此方法(v是相同的volatile int
):
void increment() {
v++;
}
你不能保证v会增加2.这是因为v++
实际上是三个陈述:
load v;
increment v;
store v;
由于线程交错,v只能递增一次(两个线程都会加载相同的值)。
答案 1 :(得分:5)
假设您有这两个变量:
public int a = 0;
public volatile int b = 0;
假设一个线程
a = 1;
b = 2;
如果另一个线程读取这些值并看到b == 2,那么它也可以保证看到== 1.
但是读取线程可以看到a == 1
和b == 0
,因为这两个写操作不是原子操作的一部分,因此读取线程可能会看到对a
之前的更改第一个线程已将值赋给b
。
要使这两个写入原子,您需要同步对这两个变量的访问:
synchronized (lock) {
a = 1;
b = 2;
}
...
synchronized (lock) {
System.out.println("a = " + a + "; b = " + b);
}
在这种情况下,阅读主题会看到a == 0
和b == 0
,或a == 1
和b == 2
,但不会是中间状态。