Java内存模型JMM
1.JMM介绍:
Java内存模型规定了所有的变量都存储在主内存(Main Memory)中,每条线程还有自己的工作内存(Working Memory),
线程的工作内存中保存了被该线程使用的变量的主内存副本,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的数据。
不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。
下图描述了线程、主内存、工作内存三者的交互关系:
package com.fll.jvm;
public class JMM_Test01 {
public static void main(String[] args) {
Number n = new Number();
//开启A线程
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"开始修改: "+n.number);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
n.addTo1000(); //将number修改成1000
System.out.println(Thread.currentThread().getName()+"已经修改好了: "+n.number);
},"线程A") .start();
//main线程
while(n.number == 10) {
//需要有一种通知机制告诉main线程,number被修改了
}
System.out.println(Thread.currentThread().getName()+":number: "+n.number);
}
}
class Number{
int number = 10;
//加上volatile之后可以增加可见性
// volatile int number = 10;
public void addTo1000() {
this.number = 1000;
}
}
执行的输出如下图:
现象:main线程一直在等待,说明main线程中的变量没有被修改。直接说明A线程修改了工作内存中的number 并上传至主内存,但是main线程也有一份之前一样的工作副本,如果不通知main线程,那么main线程将一直等下去。
但是如果将number 用volatile修饰,程序会立马结束。
volatile解析
volatile关键字是Java虚拟机提供的最轻量级的同步机制。
具备以下两个特性:
- volatile修饰的变量在多线程中保证了可见性。
- volatile修饰的变量能禁止指令重排序优化。
但是并不能保证原子性...