volatile
1.什么是volatile?
volatile是JAVA虚拟机提供的轻量级的同步机制。在前面线程安全的文章中提到了内存可见性问题。volatile就是保持了内存可见性,Java编译器对指令的优化相关
2.volatile内存可见性
volatile的可见性是多线程同步之间的一种通讯机制,在JMM中规定共享变量(实例域、静态域、数组元素)放在主内存中,非共享变量(局部变量、方法定义参数和异常处理器参数)放在每个线程自己的工作内存,每个线程在使用共享变量时会将其拷贝到自己的工作内存进行操作,但操作完成后不知道何时将其写回主内存,此时主内存的值未发生改变,其他线程嗅探到主内存的值未发生改变,导致其他线程操作了脏数据”。
3.来看一组代码案例
import java.util.Scanner;
public class ThreadDemo11 {
static class Counter{
static int count = 0;
} public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
while (Counter.count == 0){
}
System.out.println("循环结束");
});
t1.start();
Thread t2 = new Thread(()->{
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个数字");
Counter.count = scanner.nextInt();
});
t2.start();
t1.join();
t2.join();
System.out.println(Counter.count);
}
}
运行结果
分析代码
逻辑分析
如何修改
那就加上volatile关键字,显示的指定,让编译器不要优化了,让编译器每次都从内存中读取数据
对于加了volatile关键字的变量进行操作,JVM会向处理器发送一条Lock前缀的指令,将这个变量所在的缓存行的数据写回主内存,其他线程会嗅探在总线上的数据来检查自己的数据是否过期当发现自己的缓存行对应的内存地址被改变就会将当前线程中的变量置为无效,当线程需要对该变量进行操作时,会重新从主内存中读取变量最新的值,在进行操作,这样就实现了多线程之间的通信。
注意
volatile只能保证变量的内存可见性,不能保证变量的原子性,如果想要保证原子性则需要在count++时加上synchronized