Java内存模型中的先发生规则

问题描述

根据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的角度来看)。

如果您要回答问题“在我的情况下在运行时会发生什么?”。可以发生很多事情......看看这个asnwer。运行时可以执行JMM认为很重要的优化。

无论如何,如果您对内部结构感兴趣,可以查看这篇 (可以避免内存障碍)。如您所见,在生成的程序集中,执行易失性读取时未应用任何内存屏障。我的意思是运行时间无论如何都可以优化…只要保留JMM规则…

解决方法

我目前正在学习并发编程考试,不理解为什么该程序的输出为43。为什么x = y + 1以前执行t.start()?我还应该解释使用规则之前发生的情况。

如果我了解程序顺序规则(线程中的每个动作发生在该线程中的每个动作发生在程序顺序的后面)t.start()必须先执行,x = y + 1以便线程t复制变量x为1。

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;
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...