众所周知,在java多线程中,volatile关键字是一个比较重要的一个关键字。它也可被称作“轻量级”的synchronized,经常拿来和synchronized比较。和synchronized不同,volatile是一个变量修饰符,只能用来修饰变量。无法修饰方法及代码块等。
变量内存间的可见性
变量内存间的可见性是volatile最主要的功能,可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
对于普通的变量: 普通变量的值在线程间传递均需要通过主内存来完成
对于volatile关键字修饰的变量:多线程下jvm会为每个线程分配一个独立的缓存来提高效率,当一个线程修改了该变量后,另外一个线程立即可以看到。
下面代码将展示volatile关键字的使用:
package com.kevin.demo.juc;
public class juc01 {
private Boolean bool = true;
public void vola(Boolean bool) {
this.bool = bool;
}
public boolean getBool() {
return bool;
}
public static void main(String[] args) throws InterruptedException {
juc01 juc = new juc01();
new Thread(() -> {
while (juc.getBool()) {
}
System.out.println("中断结束啦!");
}).start();
Thread.sleep(500);
juc.vola(false);
}
}
沒有加volatile关键字输出的结果为死循环,一直在循环里无法打断。
package com.kevin.demo.juc;
public class juc01 {
private volatile Boolean bool = true;
public void vola(Boolean bool) {
this.bool = bool;
}
public boolean getBool() {
return bool;
}
public static void main(String[] args) throws InterruptedException {
juc01 juc = new juc01();
new Thread(() -> {
while (juc.getBool()) {
}
System.out.println("中断结束啦!");
}).start();
Thread.sleep(500);
juc.vola(false);
}
}
上述代码对变量用volatile关键字修饰了,结果输出为
这是为什么呢,下面画个简易的图解析下
没有volatile关键字时,每个线程先从主内存拷贝变量到缓存中,当bool被主线程修改后主存中并没有回写最新的bool状态。所以副线程还是从缓存读到的是true,造成死循环的结果。而加入了volatile之后,当一个线程修改该volatile修饰的变量后,会立即写回主内存,确保读操作每次都是从主内存读取。