【发布时间】:2013-11-14 12:18:36
【问题描述】:
我想亲自尝试Java lang spec example,但显然有些东西我不明白。我的理解是 volatile 计数器的递增顺序应该与代码中显示的顺序相同。 “令人惊讶的是”我得到一个随机计数器值,因为一个计数器有时小于、等于和大于另一个。 有没有人可以解释我错过了什么?
下面的代码和输出:
public class C {
private static volatile int i = 0;
private static volatile int j = 0;
static void one() {
i++;
j++;
}
static void two() {
int a = i;
int b = j;
if(a < b)
System.out.println(a + " < " + b);
if(a > b)
System.out.println(a + " > " + b);
if(a == b)
System.out.println(a + " = " + b);
}
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
while(true)
one();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while(true)
two();
}
});
t1.start();
t2.start();
Thread.sleep(5000);
System.exit(0);
}
}
输出
214559700 > 214559699
214559807 > 214559806
214559917 > 214559916
214560019 = 214560019
214560137 > 214560136
214560247 = 214560247
214560349 > 214560348
214560455 = 214560455
214560561 > 214560560
214560670 = 214560670
214560776 = 214560776
214560886 > 214560885
214560995 = 214560995
214561097 < 214561098
【问题讨论】:
-
有什么令人惊讶的?递增总是按顺序发生,但这并不意味着将值复制到
a和b或打印总是在这两个值都递增之后发生。你能澄清一下你预计会发生什么吗? -
要记住的另一件事......即使增量也不是“原子的”。如果你有两个线程同时调用 i++ 1000 次,你可能会发现执行完成时 i 不是 2000,而是少了一些值。
-
感谢您指出这一点!