【发布时间】:2015-07-07 14:42:59
【问题描述】:
如果你有以下方法,在 Java 中:
public int foo(int n) {
int i=n;
i = i+1; i = i-1;
return i;
}
因此在顺序程序中,返回值将始终与输入相同。
即:j == foo(j)
但是如果你有多个线程调用foo,你能保证j==foo(j)吗?
我会说是的,这是有保证的,因为i 是一个局部变量,每个线程都有自己的堆栈,所以i 将是每个线程的不同内存位置。
如果i 是实例变量,我会说你不能保证j==foo(j):
private int i;
public int foo(int n) {
i=n;
i = i+1; i = i-1;
return i;
}
因为线程可以交错并且i的值可以在线程执行该方法的过程中改变,或者一个线程可以增加i,但在它有机会减少它之前,另一个线程返回它的输入递增两次,仅递减一次。
【问题讨论】:
-
你的假设是正确的,但我要补充一些更可怕的东西:在你修改实例变量的情况下,绝对不能保证每次递增和递减都会按这个顺序出现线。一个线程可能会看到一个增量,然后是一个减量,另一个线程看到它们以相反的顺序发生。
-
@biziclop 我可以理解多个增量或减量,但我不明白只看到一个减量和一个增量按顺序发生?
-
规则是
In the absence of a happens before ordering between two operations, the JVM is free to reorder them as it pleases.由于在修改线程中运行的代码和在观察线程中运行的代码之间没有这种关系,所以观察线程可以看到修改的结果任何订单。 -
这个故事的真正寓意是:当并发访问发生时没有完善的顺序或操作时,不要对程序的行为做出假设。
标签: java multithreading