java 内存模型如何解决可见性和有序性问题
看标题联想
- happen before 原则
- 之后就是并发编程实战中的图形 cmp等命令
- 内存模型 又想到什么?
- 导致可见性就是因为cup的缓存,有序性就用volatile关键字呗
按需禁用缓存以及编译优化
java 内存模型很复杂,synchronized ,volatile ,final 还有happen-before 6个原则
volatile 在1.5版本才解决的可见性问题,因为加入了happen-before原则。
前一个操作的结果对后续操作是可见的,这个是happen-before的原则。
- 程序顺序规则
指的是在一个线程中前边的代码happen-before后边任意的操作
- volatile 变量规则
这条规则是指对一个 volatile 变量的写操作, Happens-Before 于后续对这个 volatile变量的读操作,需要结合第三条传递性看
传递性
A于B 操作前,B于C 操作前,那么A 必然于C 前
简单分析:
A x=42 在v=true 之前 这是A的规则,B v=true 于 读变量x 前,那么最后的结果是x =42 ,这就是传递性 最终B能读取到A的变量 x =42管程中锁的规则
管程在java 里就是synchronized 的实现 ,指的是一个管程的解锁于后续对这个锁的加锁前。
// todo没太理解,例子就是synchronized 加锁 解锁是jvm 底层用ACC-synchronized 的命令实现,而且是自动加锁和释放锁- 线程 start() 规则
比如A中启动一个线程B ,B能看到A 启动B 之前的操作 ,在A调用b.start()前 所有的操作Happens-Before 于线程 B 中的任意操作
- 线程 join() 规则
主线程调用B线程中的join 方法,那么等B线程执行完毕,那么B线程中的操作happen-before于A 调用B的join操作的返回,也就是主线程能看到join之后b线程的操作。
- 被忽略的final 关键字
用final 修饰的关键字,认为是不可变的,但是要防止逸出
小结:
其实happen-before的规则在java 语义中就是可见性,如果A happen-before B ,那么A事件对B事件就是可见的,不论发生在一个或者多个线程里。
线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事 件的发生,可以通过Thread.interrupted()方法检测到是否有中断发生。
对象终结规则:一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法 的开始