java内存模型

主内存和工作内存

  主内存是所有变量存储的地方,工作内存是当前线程的中要使用变量的主内存的副本,线程对变量的操作就在工作内存里面完成,不能直接修改主内存的变量,不同线程不能直接读写对方工作内存的变量,之间交互必须通过主内存来完成。

内存之间的交互操作

  虚拟机定义了8种原子操作来完成工作内存和主内存的交互。
  lock:将主内存中一个变量标识为一个线程独占的状态。
  unlock:将主内存中被锁住的变量解锁。
  read:将一个变量值从主内存中传输到线程的工作内存中去。
  load:将read操作读取的值放入到工作内存的变量副本中去。
  use:将工作内存中一个变量的值传递给执行引擎,当虚拟机需要使用时就会执行这个操作。
  assign:将执行引擎的值赋值给工作内存的变量。
  store:将工作内存中的值传到主内存中去。
  write:将从工作内存中得到的值放入到主内存的变量中。
  同时有以下规则:
  1.不许read和load,store和write分开执行。
  2.不许线程丢弃assign操作,也就是在工作内存中改变了值,必须同步到主内存中去。
  3.不许一个线程在没有发生assign的操作下就将数据从工作内存同步到主内存中去。
  4.一个变量在同一时刻只许一个线程对其lock.
  5.如果对一个变量lock,就会清空工作内存中该变量的值,在执行引擎使用这个变量前,需要重洗load和assign初始化这个变量的值。
  6.不许对其他线程或者没有lock的线程执行unlock。
  7.对变量执行unlock之前要先将变量同步到主内存中去。

volatile关键字

  可见性:当一个线程修改这个变量的值后,新值对其他变量是可见的。
  禁止指令重排序:指令重排序是在单线程下优化字节码的执行顺序,但是在多线程下可能出现问题,可以看本博客的单例模式下2重锁问题的解释为何要加volatile关键字。这个关键字通过内存屏障来禁止指令重排序。对于加锁和这个关键字,能用这个关键字的就不加锁,看你的业务场景吧。
  这个关键字通过以下规则保证可见性和禁止重排序。
  1.每次使用volatile变量时必须先从主内存中刷新读取最新的值。
  2.每次修改volatile变量时,必须立刻同步数据到主内存。