lma*_*uts 5 java concurrency multithreading java-memory-model happens-before
我目前正在攻读并发编程考试并且不明白为什么这个程序的输出是43.为什么x = y + 1之前执行t.start()?我还应该解释在我使用的规则之前发生了什么.
如果我理解程序顺序规则(一个线程中的每个动作发生 - 在该程序顺序后面的那个线程中的每个动作之前)t.start()都必须在执行之前执行,x = y + 1以便线程t复制变量x1.
public class HappensBefore {
static int x = 0;
static int y = 42;
public static void main(String[] args) {
x = 1;
Thread t = new Thread() {
public void run() {
y = x;
System.out.println(y);
};
};
t.start();
x = y + 1;
}
Run Code Online (Sandbox Code Playgroud)
没有同步,没有volatile字段,没有锁定,没有原子字段.代码可以按任何顺序执行.
是的,t.start()将在之前执行x = y + 1.但是启动线程并不意味着线程主体之前执行x = y + 1.它可以在其余部分之前,之后或之间运行main().
根据JMM 的说法:
对线程上的 start() 的调用发生在已启动线程中的任何操作之前。
和
如果 x 和 y 是同一线程的操作,并且 x 按程序顺序出现在 y 之前,则 hb(x, y)。
程序顺序的定义是这样的:
在每个线程t执行的所有线程间动作中,t的程序顺序是反映根据t的线程内语义执行这些动作的顺序的总顺序。
线程间语义是 JMM 中定义明确的概念。这意味着程序中每个线程执行的指令顺序必须保留为程序文本中写入的顺序。
将所有这些应用到您的案例中:
t.start(); hb x = y + 1; //程序顺序
t.start(); hb // 在此y = x; 指定的规则之前发生
如果没有额外的同步,我们就无法说明x = y + 1;和 是如何y = x; 相互关联的(从 JMM 的角度来看)。
如果您试图回答“在我的情况下运行时会发生什么?”的问题。可能会发生很多事情......看看这个答案。运行时可以执行与 JMM 一致的重要优化。
无论如何,如果您对内部结构感兴趣,可以看看这篇文章(可以避免内存障碍)。正如您在生成的程序集中看到的,执行易失性读取时不会应用内存屏障。我的意思是运行时无论如何都可以优化...只要保留 JMM 规则...
| 归档时间: |
|
| 查看次数: |
395 次 |
| 最近记录: |