java内存模型

58 阅读2分钟

简介

java内存模型(Java Memory Model,JMM)定义了多线程下内存访问的规则,屏蔽了底层硬件的差异,目的是解决多线程环境下共享数据的原子性、可见性、和有序性。理解 JMM 是编写正确、高效并发程序的基础,synchronized、volatile、final 等关键字均基于 JMM 实现其语义。

核心概念

  1. 主内存(Main Memory)
    共享变量存在主内存中,线程共享。
  2. 工作内存(Working Memory)
    每个线程有自己的工作内存,存错操作主内存变量的副本。线程对变量的操作在自己的工作内存中修改,不能直接操作主内存
  3. 内存屏障(Memory Barrier)
    一组规则,用于控制指令重排序和内存可见性,例如 volatile、synchronized 等关键字会插入内存屏障。

三大特性

  1. 可见性(Visibility)
    多线程对共享变量的修改必须对其他线程可见

  2. 原子性(Atomicity)
    对共享变量的修改要么全部执行成功,要么不执行

  3. 有序性(Ordering
    程序执行的顺序需符合预期,避免因指令重排序导致结果异常

Happens-Before 规则

  • 程序次序法则:
    线程中的每个动作A都happens-before于该线程中的每一个动作B,其中,在程序中,所有的动作B都出现在动作A之后。

  • 监视器锁法则:
    对一个监视器锁的解锁happens-before 于每一个后续对同一监视器锁的加锁。

  • volatile 变量法则:
    对 volatile 域的写入操作 happens-before 于每一个后续对同一域的读操作.

  • 线程启动法则:
    在一个线程里,对Thread.start的调用会happens-before 于每一个启动线程中的动作。即在主线程调用子线程的start()方法前的所有操作对子线程可见。

  • 线程终结法则:
    线程中的任何动作都happens-before 于其他线程检测到这个线程已经终结、或者从 Thread.join 调用中成功返回,或者 Thread.isAlive 返回 false.即在主线程中调用子线程的join()方法,子线程中所有的操作对主线程可见。

  • 中断法则:
    一个线程调用另一个线程的interrupt happens-before 于被中断的线程发现中断(通过抛出InterruptedException,或者调用 isInterrupted 和interrupted ).

  • 终结法则:
    一个对象的构造函数的结束happens-before于这个对象finalizer的开始。

  • 传递性:
    如果Ahappens-before于B,且B happens-before于C,则A happens-before于C.