- Java并发编程模型的两个关键问题,是什么?
- Java内存模型的抽象结构是怎么样的
- Java代码到最终的运行有哪些指令的重排序
- 并发编程模型分类:这个作者容和实际阐述不符
-
并发模型的两个关键问题
- 线程之间如何通信
- 线程之间如何同步
我认为线程之间的通信是同步的条件,没有通信何来同步?
Java内存模型的抽象结构
- 共享变量:所有的实例域、静态域等堆内存中的数据
- JMM决定一个共享变量的写入何时对另一个线程可见,定义了主内存和线程本地内存的抽象关系
- 本地内存是个抽象概念并不真实存在,包含:缓存、写缓冲、寄存器等
源代码到指令序列的重排序
- 3种指令重排序
- 编译器优化重排序:字节码
- 指令级并行重排序:处理器改变语句对应机器指令的执行顺序
- 内存系统重排序:处理器使用缓存和读写缓冲。使得数据加载存储可能是乱序的
- JMM如何防止指令重排序的影响
- 编译器级别:JMM可以禁止某些操作在编译器阶段禁止重排序
- 指令级别:可以在正常的指令序列中,插入内存屏障指令
JMM作用
程序顺序规则:在单线程中,代码在前面的操作happens-before后面的操作
- 监视器规则:加锁前一定在上一个解锁之后执行
- volatile变量规则:对于一个volatile修饰的变量,写操作happends-before后续的任意读操作
- 传递性:A->B B->C => A->C
如何理解一句话
两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行!happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见
举个例子:
在一个单线程中,执行下面的代码:
int a = 1;
int b = 2;
按照happends-before规则,大家可能会认为 a=1一定比b=1先完成赋值,其实不一定。因为happens-before的真正含义是:应该是当两个操作有关联时,前一个操作对后一个操作可见。a=1和b=1两个操作没有联系。所以不一定a=1先被执行。
为啥要定义这些规则
对于程序员,作用主要是开发业务,我不可能再去学习JMM到底怎么实现的。于是JMM将自己的实现简化为几个规则。程序员无需关心实现,只要谨记结论即可。
- JMM定义一套底层实现的规范
- NB的程序员根据JMM这套规则对JMM这套规则进行实现
- JMM实现后,Java程序并发编程时就满足happens-before这套规则
- happens-before是实现JMM后的结果