关于java:Java-内存模型-JMM-Java-Memory-Model

58次阅读

共计 1245 个字符,预计需要花费 4 分钟才能阅读完成。

Java 内存模型 JMM (Java Memory Model)

要搞懂并发编程必须搞懂 JMM.

JMM 屏蔽了不同操作系统中的内存差异性. 定义了线程和主内存之前的形象关系。

线程之间的共享变量存储在主内存中,每个线程都有一个公有的本地内存, 本地内存存储了该线程以读 / 写共享变量的正本。本地内存是 JMM 的一个抽象概念,并不实在存在。它涵盖了缓存、写缓冲区、寄存器以及其余的硬件和编译器优化。

JMM 形象示意图如下:

从上图来看,线程 A 和 B 操作的共享变量都是本地内存中的正本,如果想要相互看到对方操作之后的共享变量,就须要给本地内存的共享变量正本刷到主内存外面去,同时另一个线程从主内存读取共享变量。

JMM 通过管制主内存与每个线程的本地内存之间的交互,来为 咱们提供内存可见性保障。

happens-before 准则

这个有点绕。。。须要好好了解一下。

JSR-133 应用 happens-before 来论述操作之间的内存可见性。

在 JMM 中 如果操作执行的后果须要对另一个操作可见,那么这两个操作之间必须要存在 happens-before 关系。

与咱们密切相关的 happens-before 规定如下:

  • 程序程序规定

    一个线程外面的每一个操作,happens-before 于该线程中的任意后续操作。

    直白点就是 一个线程外面每一个操作的后果 对于前面的操作都是可见的。

  • 监视器锁规定

    对一个锁的解锁,happens-before 于随后对这个锁的加锁。

    翻译一下 大略是 某个持有锁的线程操作的后果在开释之后,对获取该锁的线程可见

  • volatile 变量规定

    对一个 volatile 域的写,happens-before 于任意后续对这个 volatile 的读。

    翻译版:对 volatile 的写,对于后续 读该 volatile 域的线程是可见的。volatile 的 内存语义。

  • 传递性

    如果 A happens-before B,B happens-before C 那么 A happens-before C

volatile 变量 写 -> 读 的内存语义

volatile 变量本身具备下列个性:

  • 可见性

    对一个 volatile 变量的读,总是能看到 (任意线程) 对这个 volatile 变量最初的写入。

  • 原子性

    对任意单个 volatile 变量的读 / 写具备原子性,但相似于 volatile++ 这种复合操作不具备原子性。

下面是 volatile 本身的个性,如下是 JDK5 之后加强的内存语义。

从 JSR-133 开始(JDK5 开始),volatile 变量的写 – 读 能够实现线程之间的通信。

从内存语义的角度来看,volatile 的写 - 读 和 锁的开释 - 获取有雷同的内存成果(参考下面监视器规定)。

volatile 写

当写一个 volatile 的变量时,JMM 会把该线程对应的本地内存中的共享变量值刷新到主内存当中。

volatile 读

当读一个 volatile 变量时,JMM 会把该线程对应的本地内存置为有效,该线程将从主内存中读取共享变量。

参考资料

  • The Java® Language Specification
  • Java 并发编程的艺术
  • JSR-133
正文完
 0