java-1.5 jvm-jmm

75 阅读3分钟

JVM内存模式指的是JVM的内存分区;而Java内存模式是一种虚拟机规范。

The Java memory model describes how threads in the Java programming language interact through memory.

Java的多线程之间是通过共享内存进行通信的,而由于采用共享内存进行通信,在通信过程中会存在一系列如可见性、原子性、顺序性等问题,而JMM就是围绕着多线程通信以及与其相关的一系列特性而建立的模型。JMM定义了一些语法集,这些语法集映射到Java语言中就是volatile、synchronized等关键字。

Java 内存模型的抽象

在 java 中,所有实例域、静态域和数组元素存储在堆内存中,堆内存在线程之间共享(本文使用“共享变量”这个术语代指实例域,静态域和数组元素)。

局部变量(Local variables),方法定义参数(java 语言规范称之为 formal method parameters)和异常处理器参数(exception handler parameters)不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响。

Java 线程之间的通信由 Java 内存模型(本文简称为 JMM)控制,JMM 决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM 定义了线程和主内存之间的抽象关系:

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

Java 内存模型的抽象示意图如下:

image.png

处理器重排序与内存屏障指令

为了保证内存可见性,java 编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。JMM 把内存屏障指令分为下列四类:

image.png

JMM解决的问题

并发程序正确地执行,必须要保证原子性、可见性以及有序性.只要有一个没有被保证,就有可能会导致程序运行不正确.

  • 原子性 在java中提供了两个高级的字节码指令monitorenter和monitorexit,在Java中对应的Synchronized来保证代码块 内的操作是原子的

  • 可见性 Java中的volatile关键字提供了一个功能,那就是被其修饰的变量在被修改后可以立即同步到主内存,被其修饰的变 量在每次是用之前都从主内存刷新。因此,可以使用volatile来保证多线程操作时变量的可见性。 除了volatile,Java中的synchronized和final两个关键字也可以实现可见性

  • 有序性 volatile关键字会禁止指令重排。synchronized关键字保证同一时刻只允许一条线程操作。