美文网首页
JMM之重排序

JMM之重排序

作者: T_log | 来源:发表于2018-10-10 15:37 被阅读12次

重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段

  1. 在程序执行时,为了提高性能,编译器和处理器通常会对指令进行重排序,但是不能随意的重排序,必须满足一下两点
  • 单线程情况下,不能改变程序执行结果
  • 存在数据依赖性关系的操作之间不能重排序

数据的依赖性

  1. 如果两个操作访问同一个共享变量,且这两个操作有一个是写操作,那么这两个操作之间就存在数据依赖性
  2. 编译器和处理器会在重排序时,遵守数据依赖性,编译器和处理器不会改变存在数据依赖性的两个操作的执行顺序
  3. 这里的数据依赖性也只是针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑

as-if-serial语义

  1. as-if-serial语义的意思是,不管怎么重排序(编译器和处理器为了提高并行度),单线程程序的执行结果不能改变。编译器、runtime和处理器都必须遵守as-if-serial语义
  2. 为了遵守as-if-serial语义,编译器和处理器不会对存在数据依赖性的操作重排序,因为一旦重排序,就可能会影响程序的执行结果,对于不存在数据依赖性的操作,是可能会被编译器和处理器做重排序处理
int a = 1; //A
int b = 2; //B
int c = a + b; //C
  1. 上面的数据依赖性关系是,C依赖于A和B,而A和B之间不存在数据依赖性,因此编译器可以对A和B进行重排序
  2. as-if-serial语义给我们一个错觉,遵守as-if-serial语义的编译器和处理器,在单线程的情况下,程序是按照顺序执行,其实,对于不存在数据依赖性的操作,编译器和处理器可以随意的对其进行重排序操作,以提高执行效率

程序顺序规则

  1. 根据happens-before的程序规则,上面的例子中
  • A happens-before B
  • B happens-before C
  • A happens-before C
  1. 这里的A happens-before C是根据happens-before的传递性推导出来的

重排序对多线程的影响

  1. 如下代码块
class Example {
    int a = 0;
    boolean flag = false;
    public void writer() {
        a = 1;  //  1
        flag = true;  //  2
    }
    public void reader() {
        if (flaf) {  //  3
            int i = a + a;  //  4
        }
    }
}
  1. falg变量是一个标记,用来标记变量a是否已被写入,假如有线程A和线程B,A先执行writer,B执行reader,线程B在执行操作4时, 能否看到线程A在操作1对共享变量a的写入呢?答案是不一定能看到,由于1和2之间没有数据依赖性,编译器和处理器可以对这两个操作进行重排序,二3和4之间没有数据依赖性,编译器和处理器也可以对这两个操作进行重排序,当1和2进行重排序时,线程B执行的结果就处于一种待定的情况了

参考
周志明 《深入理解Java虚拟机》
方腾飞 《Java并发编程的艺术》

写在最后

我从未感觉如此强烈,我的灵魂离我如此遥远,而且的存在却如此的真实

相关文章

  • JMM之重排序

    重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段 在程序执行时,为了提高性能,编译器和处...

  • JMM之重排序

    重排序定义 在前面我们提到过,重排序是编译器和处理器为了优化程序性能而对指令序列重新排序的一种手段。但是我们也知道...

  • JMM - 重排序

    计算机在执行程序时,为了提高性能,编译器和处理器尝尝会对指令做重排 编译器优化重排 编译器在不改变单线程程序语义的...

  • JMM内存模型之重排序

    重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。 1. 数据依赖性 如果两个操作访问同...

  • JMM内存模型之happens-before

    JMM把happens-before 要求禁止的重排序分为了下面两类。 会改变程序执行结果的重排序。 不会改变程序...

  • JMM之重排序和happens-before

    1.什么是数据依赖性? 如果两个操作访问同一个变量,且有一个是写操作,此时两个操作就存在数据依赖性。 编译器和处理...

  • JMM之重排序&Happens-Before

    并发编程中,需要处理两个关键问题: 线程之间如何通信?—共享内存+消息传递 线程之间如何同步? java的并发采用...

  • volatile

    一、volatile可见性和禁止重排序是怎么实现的? 首先从JMM内存模型层面,volatile通过storest...

  • 数组排序去重

    冒泡排序 sort排序 数组去重

  • JVM结构和Java内存模型

    //TODOJVM结构:堆方法区栈本地方法栈程序计数器 栈帧结构: JMM内存模型:happen before 重排序

网友评论

      本文标题:JMM之重排序

      本文链接:https://www.haomeiwen.com/subject/qgnpaftx.html