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(解锁):作用于主内存的变量 , 它把一个处于锁定状态的变量释放出来 , 释放后的变量才可以被其他线程锁定 。
我再补充一下JMM对8种内存交互操作制定的规则吧: