面试题答案
一键面试volatile关键字保证可见性原理
当一个变量被声明为volatile
时,它会有以下特性来保证可见性:
- 禁止指令重排序:
volatile
变量相关的操作不会和其他指令重排序,确保对volatile
变量的写操作会在其他操作之前执行完成,并且对volatile
变量的读操作会在其他操作之后执行开始。 - 内存屏障:在写操作时,会在写操作后插入一个写屏障,保证在写屏障之前的所有写操作都刷新到主内存中;在读操作时,会在读操作前插入一个读屏障,保证在读屏障之后的读操作都能读到主内存中的最新值。这样,当一个线程修改了
volatile
变量的值,其他线程能够立即看到这个修改。
代码示例
public class VolatileExample {
private static volatile boolean flag = false;
public static void main(String[] args) {
new Thread(() -> {
System.out.println("子线程开始执行");
while (!flag) {
// 等待flag变为true
}
System.out.println("子线程结束执行");
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("主线程修改flag为true");
}
}
在上述代码中,子线程会一直循环等待flag
变为true
。主线程在休眠1秒后将flag
设置为true
。由于flag
被声明为volatile
,主线程修改flag
的值后,子线程能够立即看到这个变化,从而结束循环。如果flag
没有声明为volatile
,子线程可能永远无法感知到flag
的变化,因为子线程可能会从自己的工作内存中读取到旧的flag
值。