理解Java中的happens-before规则?

新手上路,请多包涵
class ReorderExample {
  int a = 0;
  boolean volatile flag = false;
  public void writer() {
      a = 1;                   //1
      flag = true;             //2
  }
  Public void reader() {
      if (flag) {                //3
          int i =  a * a;        //4
          System.out.println(i);
      }
  }
}

这段代码如果2在3之前发生,那根据happens-before规则,确实会输出1。但是,就算先执行writer()方法,再执行reader()方法,在多线程情况下,也可能3比2先执行,就不会输出东西。请问我理解得对吗?

阅读 957
2 个回答

没什么问题呀,happens-before规则的这三条可以得出如果2在3之前发生,输出1这个结论。
1.在一个线程中,按照代码的顺序,前面的操作Happens-Before于后面的任意操作
2.对一个volatile变量的写操作,Happens-Before于后续对这个变量的读操作
3.如果A Happens-Before B,并且B Happens-Before C,则A Happens-Before C
多线程情况下你没有使用锁或者synchronized来实现线程同步的话,2和3的执行顺序就是没有办法确定的

你理解的对

理解 happens-before 不仅要从英文单词上理解执行的先后顺序,也要从计算机重叠执行指令的层面理解,即将 A happens-before B 理解成 A 的操作结果对 B 操作是可见的

我们都知道 JVM 运行内存模型分为主内存工作内存,主内存是多个线程共享的内存区域,工作内存是线程独有的内存区域,线程展开具体工作之前都要将主内存的数据复制到工作内存中,再对工作内存的数据进行读取和修改等操作。

你给出的示例,在多线程运行的环境下,始终有一个确定的顺序,要么 2 先执行要么 3 先执行,但是在这两个确定的顺序下所得到的结果却有多个。

  • 2 先执行【正常】输出1
  • 2 先执行【特例】不输出1,因2执行完将数据保存在线程的工作内存中,此时3读取主内存得到的数据仍为false
  • 3 先执行【正常】不输出

happens-before 原则在这里起到的作用是保证在多线程执行环境下,不会得到【特例】的执行结果。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏