java多线程可见性
1、可见性介绍
1.1、可见性
1.2、java内存模型JMM
java内存模型( Java Memory Model): 描述了java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。
1.3、两条规定
- 线程对共享变量的所有操作都必须在自己的工作内存中进行,不能从主内存中读写。
- 不同线程之间无法直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成。
1.4、共享变量可见性实现的原理
流程如图:
2、synchronized实现可见性
2.1、JMM关于synchronized的两条规定
2.2、线程执行互斥代码的过程
- 获得互斥锁
- 清空工作内存
- 从主内存拷贝变量的最新副本到工作内存
- 执行代码
- 将更改后的共享变量的值刷新到主内存中
- 释放互斥锁
2.3、了解重排序和as-if-serial
重排序不会给单线程带来内存可见性问题,
多线程中程序交错执行时,重排序可能会造成内存可见性问题。
2.4、可见性分析
导致共享变量在线程间不可见的原因:
- 线程的交叉执行
- 重排序结合线程交叉执行
- 共享变量未及时更新
synchronized实现可见性代码:在读、写操作的方法上加上synchronized (对应上面出现问题的解决方案)
- 原子性
- 原子性
- 可见性
3、volatile实现可见性
深入来说:通过加入内存屏障和禁止重排序优化来实现的。
- 对volatile变量执行写操作时,会在写操作后加入一条store屏障指令。
- 对volatile变量执行读操作时,会在读操作前加入一条load屏障指令。
通俗地讲: volatile变量在每次被线程访问时,都强迫从主内存中重读该变量的值,而当该变量发生变化时,又会强迫线程将最新的值刷新到主内存,这样任何时刻,不同的线程总能看到该变量的最新值。
线程写volatile变量的过程:
线程读volatile变量的过程:
4、synchronized和volatile比较
本人从慕课网上学习,记录的笔记。