Java内存模型

Java Memory Model and Thread Specification
JMM是和线程相关的规范,JMM主要解决多线程环境下,线程之间的通信。

多线程环境下,CPU Cache和主内存之间数据不一致问题。
alt

JMM的角色:

JMM管理的程序变量,主要是指在对象实例字段、静态字段、构成数组字段的元素等,不包括方法参数、方法局部变量等保存在栈里的变量,因为栈本身就是线程私有的,并不存在线程一致性问题

alt

指令重排(Reordering)

编译器指令的重排
编译器在不改变单线程程序语义的前提下,可以重新调整语句的执行顺序

处理器指令级并行的重排
现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序

内存系统的重排
由于处理器使用缓存和读/写缓冲区,这使得主内存和工作内存间的数据加载和存储操作看上去可能是在乱序执行的

JMM的编译器重排序规则会禁止volatile变量、synchronized、final等特定指令的编译器重排序

Happens-before规则

程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。
start()规则:如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作。
join()规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。
程序中断规则:对线程interrupted()方法的调用先行于被中断线程的代码检测到中断时间的发生。
对象finalize规则:一个对象的初始化完成(构造函数执行结束)先行于发生它的finalize()方法的开始。

顺序一致性的解决方案:

volatile变量
注意变量+1这种,非原子操作,属于read,load,use,需要自行使用synchronized/Reentrantlock进行同步,或者直接使用tomicInteger之类的。

synchronized关键字

final关键字

https://segmentfault.com/a/1190000021637869

http://www.jiangxinlingdu.com/concurrent/2019/02/16/java-memory-model.html

堆heap 和 栈stack

alt

注意stack会出现StackOverflowError
线程栈的空间大小-Xss 默认是1M

单纯是增加 -Xss 一般都没用 需要检查是否存在递归无限调用,导致线程栈空间不足