• Java并发编程模型的两个关键问题,是什么?
  • Java内存模型的抽象结构是怎么样的
  • Java代码到最终的运行有哪些指令的重排序
  • 并发编程模型分类:这个作者容和实际阐述不符
  • [x] happens-before模型

    并发模型的两个关键问题

    • 线程之间如何通信
    • 线程之间如何同步

我认为线程之间的通信是同步的条件,没有通信何来同步?

Java内存模型的抽象结构

  • 共享变量:所有的实例域、静态域等堆内存中的数据
  • JMM决定一个共享变量的写入何时对另一个线程可见,定义了主内存和线程本地内存的抽象关系
  • 本地内存是个抽象概念并不真实存在,包含:缓存、写缓冲、寄存器等

image.png

源代码到指令序列的重排序

  1. 3种指令重排序
    • 编译器优化重排序:字节码
    • 指令级并行重排序:处理器改变语句对应机器指令的执行顺序
    • 内存系统重排序:处理器使用缓存和读写缓冲。使得数据加载存储可能是乱序的
      image.png
  2. JMM如何防止指令重排序的影响
    • 编译器级别:JMM可以禁止某些操作在编译器阶段禁止重排序
    • 指令级别:可以在正常的指令序列中,插入内存屏障指令
  3. JMM作用

    • 为程序员屏蔽不同编译器和不同处理器之间的差异,保证一套唯一的内存可见性规则

      内存屏障有哪些

      image.png

      happens-before规则

  4. 程序顺序规则:在单线程中,代码在前面的操作happens-before后面的操作

  5. 监视器规则:加锁前一定在上一个解锁之后执行
  6. volatile变量规则:对于一个volatile修饰的变量,写操作happends-before后续的任意读操作
  7. 传递性:A->B B->C => A->C

    如何理解一句话

    两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行!happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见

举个例子:
在一个单线程中,执行下面的代码:

  1. int a = 1;
  2. int b = 2;

按照happends-before规则,大家可能会认为 a=1一定比b=1先完成赋值,其实不一定。因为happens-before的真正含义是:应该是当两个操作有关联时,前一个操作对后一个操作可见。a=1和b=1两个操作没有联系。所以不一定a=1先被执行。

为啥要定义这些规则

对于程序员,作用主要是开发业务,我不可能再去学习JMM到底怎么实现的。于是JMM将自己的实现简化为几个规则。程序员无需关心实现,只要谨记结论即可。
image.png

  1. JMM定义一套底层实现的规范
  2. NB的程序员根据JMM这套规则对JMM这套规则进行实现
  3. JMM实现后,Java程序并发编程时就满足happens-before这套规则
  4. happens-before是实现JMM后的结果