Java|面试官问我什么是JMM( 二 )
可见性
可见性指当一个线程修改共享变量的值 , 其他线程能够立即知道被修改了 。 Java是利用volatile关键字来提供可见性的 。当变量被volatile修饰时 , 这个变量被修改后会立刻刷新到主内存 , 当其它线程需要读取该变量时 , 会去主内存中读取新值 。 而普通变量则不能保证这一点 。
除了volatile关键字之外 , final和synchronized也能实现可见性 。
synchronized的原理是 , 在执行完 , 进入unlock之前 , 必须将共享变量同步到主内存中 。
final修饰的字段 , 一旦初始化完成 , 如果没有对象逸出(指对象为初始化完成就可以被别的线程使用) , 那么对于其他线程都是可见的 。
有序性
在Java中 , 可以使用synchronized或者volatile保证多线程之间操作的有序性 。 实现原理有些区别:
volatile关键字是使用内存屏障达到禁止指令重排序 , 以保证有序性 。
synchronized的原理是 , 一个线程lock之后 , 必须unlock后 , 其他线程才可以重新lock , 使得被synchronized包住的代码块在多线程之间是串行执行的 。
面试官:给我讲一下八种内存交互操作吧
好的 , 面试官 , 内存交互操作有8种 , 我画张图给你看吧:
- lock(锁定) , 作用于主内存中的变量 , 把变量标识为线程独占的状态 。
- read(读取) , 作用于主内存的变量 , 把变量的值从主内存传输到线程的工作内存中 , 以便下一步的load操作使用 。
- load(加载) , 作用于工作内存的变量 , 把read操作主存的变量放入到工作内存的变量副本中 。
- use(使用) , 作用于工作内存的变量 , 把工作内存中的变量传输到执行引擎 , 每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作 。
- assign(赋值) , 作用于工作内存的变量 , 它把一个从执行引擎中接受到的值赋值给工作内存的变量副本中 , 每当虚拟机遇到一个给变量赋值的字节码指令时将会执行这个操作 。
- store(存储) , 作用于工作内存的变量 , 它把一个从工作内存中一个变量的值传送到主内存中 , 以便后续的write使用 。
- write(写入):作用于主内存中的变量 , 它把store操作从工作内存中得到的变量的值放入主内存的变量中 。
- unlock(解锁):作用于主内存的变量 , 它把一个处于锁定状态的变量释放出来 , 释放后的变量才可以被其他线程锁定 。
- 不允许read、load、store、write操作之一单独出现 , 也就是read操作后必须load , store操作后必须write 。
- 不允许线程丢弃他最近的assign操作 , 即工作内存中的变量数据改变了之后 , 必须告知主存 。
- 不允许线程将没有assign的数据从工作内存同步到主内存 。
- 一个新的变量必须在主内存中诞生 , 不允许工作内存直接使用一个未被初始化的变量 。 就是对变量实施use、store操作之前 , 必须经过load和assign操作 。
- 一个变量同一时间只能有一个线程对其进行lock操作 。 多次lock之后 , 必须执行相同次数unlock才可以解锁 。
- 如果对一个变量进行lock操作 , 会清空所有工作内存中此变量的值 。 在执行引擎使用这个变量前 , 必须重新load或assign操作初始化变量的值 。
推荐阅读
- Java|淘宝商家要小心了!取消的“中差评”体系又回来啦!
- javascript|游戏开发之旅-JavaScript重新介绍
- Java|java多线程并发小demo
- Java|java程序猿如何才能走远,怎么做自己的职业规划
- 蚂蚁花呗|血亏!阿里P8轻易把总结了近一年的java高级特性笔记送人了
- jvm|清纯小学妹连续被三个大汉硬怼:JVM学成这样,还敢来面试?
- 百度|Java高级进阶多线程学习之路(七)ThreadLocal
- javascript|家里宽带是300M的,但是实际测速才2M应该这样维权。
- 社交|十一国庆过后,秋招Java岗,陆续收到字节/招银等offer
- Java|Java面试之基础问题答案口述整理