volatile

volatile是一个关键字,用于修饰变量,如private volatile boolean falg = false;,当一个变量用volatile修饰时,表示该变量是一个共享变量,它可以被多个线程访问。它的作用主要有两个方面

保证可见性

当在一个线程当中修改了用volatile关键字修饰的变量,那么它会立即同步到主内存当中,其他线程读取这个变量的值的时候,是直接读取内存中这个变量的值,而不是在当前线程中的缓存;同时也避免了多线程数据不一致的问题

禁止指令重排序

在没有使用volatile关键字的时候,JVM会进行指令重排序以优化执行效率,这样在使用多线程时会造成一些问题,使用了volatile关键字,就相当于告知了JVM不要对被修饰的变量进行指令重排序,比如:

有一个write()方法负责更改某个变量的值,read()方法用于读取某个变量的值,这时候有两个线程,第一个线程负责执行write()方法,第二个线程负责执行read()方法,如果此时JVM对指令进行重排序,有可能第二个线程先执行read()方法,这样就违背了预期的执行顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ReorderingExample {
private int x = 0;
private volatile boolean flag = false;

public void write() {
x = 42; // 语句1
flag = true; // 语句2
}

public void read() {
if (flag) { // 语句3
System.out.println("x = " + x); // 语句4
}
}
}

什么时候指令进行重排序?

  • 在单线程环境下不能改变程序运行的结果
  • 存在数据依赖关系的不允许重排序