FAQ-JMM

JMM Java 内存模型
  • 定义程序中各个变量的访问规则,即变量是如何存入内存、如何从内存取出的;

    变量包括:实例字段、静态字段、构成数组对象的元素,但不包括线程私有的局部变量和方法参数(不会被共享,也就不存在竞争问题)

  • 工作内存与主内存

    • 所有的变量都存在主内存中
    • 每条线程有自己独立的、相互隔离的工作内存,保存了被该线程使用的变量的主内存副本拷贝;线程对变量的所有操作都必须在工作内存进行,不能直接读写主内存的变量
    • 线程间变量值的传递均需要通过主内存来完成
  • 内存间交互操作


    FAQ-JMM_第1张图片
    • 操作规则:
      • 不允许 readloadstorewrite 操作之一单独出现;从主内存读取的变量必须要装载到工作内存、工作内存发起存储的变量必须要写入主内存
      • 不允许一个线程丢弃最近的 assign 操作;变量改变了必须同步到主内存
      • 不允许一个线程在未发生任何 assign 操作时,把数据从线程的工作内存同步到主内存
      • 新变量只能在主内存中产生,不允许在工作内存中直接使用一个未 loadassign 的变量
      • 一个变量同一时刻只允许一条线程对其进行 lock 操作
      • 对一个变量执行 lock 操作,会清空工作内存中此变量的值;使用这个变量前,需重新 loadassign 初始化变量的值
      • 变量没有 lock 则不允许 unlock
      • 对一个变量执行 unlock 操作前,必须先把次变量同步回主内存( storewrite 操作)
    • volatile 变量的特殊规则
      • 对所有线程的可见性
        • 对 volatile 变量所有的写操作都能立即反应到其他线程之中(每次使用之前都要先刷新)
      • 线程内有序性,禁止指令重排序
        • 线程内表现为串行的语义 (Within-Thread As-If-Serial Semantics)
        • 在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行
      • 只有原子操作才是并发安全的
        • i++; 典型场景
    • long 和 double 型变量的特殊规则
      • 运行虚拟机将没有被 volatile 修饰的 64 位数据的读写操作划分为两次 32 位的操作来进行;非原子性协定(Nonatomic Treatment of double and long Variables)
      • 多线程可能会出现半个变量的情况(非常罕见)
      • 实际开发中多数虚拟机都把 64 位数据的读写操作作为原子操作对待
关键字 原子性 可见性 有序性
synchronized
volatile ×
final - -

参考

  • wiki
  • specs
  • 深入理解 Java 虚拟机 第 12 章 Java 内存模型与线程

你可能感兴趣的:(FAQ-JMM)