一、内存模型图

image-20220613223300453

二、四项规定

  • 所有的变量都存储在主内存中

    说明:变量包括 成员变量静态变量构成数组的元素,不包括局部变量和方法形参(它们放在虚拟机栈中)

  • 每条线程都有自己的工作内存,且被该线程使用的变量,拷贝了一份该变量在主内存中的值

  • 线程对变量的所有操作,都必须在工作内存中进行,而不能直接读写主内存中的数据

  • 线程间变量值的传递,需要通过主内存作为中转来完成

三、八大操作与六大约束

JMM读写流程

八大操作

Java内存模型定义了 8 种操作,8种操作都具有原子性

  • lock(锁定)

    功能:把一个变量标识为一条线程独占的状态(锁定主内存变量)

  • unlock(解锁)

    功能:把一个处于锁定状态的变量释放出来,从而允许被其他线程锁定(解锁主内存变量)

  • read(读取)

    功能:把一个变量的值从主内存传输到工作内存中(传输主内存值到工作内存中)

  • load(载入)

    功能:把从主内存传输过来的值放入到工作内存的变量副本中(系统给工作变量赋值)

  • use(使用)

    功能:把工作内存变量的值传递给执行引擎(虚拟机遇到使用变量值的字节码指令时,执行该操作)

  • assign(赋值)

    功能:把执行引擎接收到的值赋值给工作内存中的变量(虚拟机遇到给变量赋值的字节码指令时,执行该操作)

  • store(存储)

    功能:把工作内存变量的值存储到主内存中(传输工作内存变量的值到主内存)

  • write(写入)

    功能:把工作内存中得到的变量的值写入主内存的变量中

六大约束

  • 成对出现:read和load、store和write
  • 对工作内存变量进行assign操作后,必须将该值同步回主内存;没有对共享变量进行assign操作,是不允许将变量的值同步会主内存
  • 新变量只能在主内存中生成,不允许在工作内存中直接使用未初始化的变量
    也就是说,对共享变量使用(use)之前,必须要先执行 load操作;对共享变量存储(store)之前,必须要先执行 assign操作
  • lock操作需要成对出现,当前线程对当前变量的lock操作,不允许去解锁其他线程被锁定的变量
  • 同一时刻,只能一个线程对变量进行lock操作,且该操作可被同一个线程执行多次,但多次lock操作必须要有相对应的 unlock 操作
  • unlock操作之前,必须将变量的新值同步写入主内存

四、八条 Happens-Before规则

  • 程序次序规则(Program Order Rule)

  • volatile 变量规则(Volatile Variable Rule)

    对 volatile 变量的写操作 比 对它的读操作要优先

  • 监视器锁定规则(Monitor Lock Rule)

    对于同一个锁, unlock操作比 lock操作优先发生

  • 线程启动规则(Thread Start Rule)、线程中断规则(Thread Interruption Rule)、线程终止规则(Thread Termination Rule)

    Thread对象的 start() 方法 比 其他方法优先

    对线程 interrupt() 方法的调用 比 被中断线程的检测方法(Thread::interrupted)优先

    线程的所有方法 比 对线程的终止检测的方法 优先

  • 对象终结规则(Finalizer Rule)

    对象的初始化 优先于 对象的finalize() 方法的调用

  • 传递性(Transitivity)

    如果操作A 先于 操作B,操作B 先于 操作C,那么可以得出 操作A 先于 操作C。