JVM我们很熟悉,那么JMM是什么呢?
JMM(Java Memory Model)定义了JVM在计算机内存(RAM)中的工作方式。JVM是整个计算机虚拟模型,所以JMM是隶属于JVM的。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。
- 记住JMM并不是真实存在的,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式
Volatile是Java虚拟机提供的轻量级的同步机制,Volatile三个特点:
- 保证可见性
- 不保证原子性
- 禁止指令重排
当多个线程在操作成员变量的时候会造成数据被更改后,但是未及时刷新到主内存中,导致其它线程不可见,所以会存在问题,如下图:
JMM内存图.jpg

再来看看一段代码:
package com.tg01;
class Person {
int age = 0;
public void addAge() {
age = 18;
}
}
public class VolatileTest {
public static void main(String[] args) {
Person person = new Person();
// 子线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " ageAge前: " + person.age);
// 模拟延时
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
person.addAge();
System.out.println(Thread.currentThread().getName() + " ageAge后: " + person.age);
}
}, "子线程").start();
// 主线程
while (person.age == 0) {}
System.out.println(Thread.currentThread().getName() + "MainThred over,age = " + person.age);
}
}
- 打印结果为:

- 程序并没有结束,会一直在循环,为什么呢?原因很简单,是因为子线程在修改age的值之后,主线程并不知道,所以主线程就一直卡住了,那么这种问题我们怎么解决呢?
- 有的人说加上synchronized同步代码块,这个当然可以,但是显得太笨重。
- 这时候我们用Volatile关键字试试?
- 在int age = 0,加上Volatile关键字,把代码修改如下:
package com.tg01;
class Person {
volatile int age = 0;
public void addAge() {
age = 18;
}
}
public class VolatileTest {
public static void main(String[] args) {
Person person = new Person();
// 子线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " ageAge前: " + person.age);
// 模拟延时
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
person.addAge();
System.out.println(Thread.currentThread().getName() + " ageAge后: " + person.age);
}
}, "子线程").start();
// 主线程
while (person.age == 0) {}
System.out.println(Thread.currentThread().getName() + "MainThred over,age = " + person.age);
}
}
- 打印结果:

- 但是这里要注意Volatile并保证原子性,比如int number,number++,可以修改成为AtomicInteger这个类操作即可。
那么Volatile还有哪些应用呢?
- 单例模式
- 禁止指令重排