volatile是什么?
volatile是java中的一个关键字; 它可以用来修饰成员变量;被它修饰的变量可以保证可见性.
什么是可见性?
可见性是指多个线程访问同一个共享变量时, 如果某个线程对共享变量进行了修改, 那么其他线程读取到的必须是修改后的值.这就是可见性.
先来看看常见的可见性问题:
class Game extends Thread {
public int index = 0;
public void setIndex(int index) {
this.index = index;
}
public int getIndex() {
return index;
}
@Override
public void run() {
System.out.println("Game Start");
while (true) {
if (getIndex() == -1) {
break;
}
}
System.out.println("Game End");
}
public static void main(String[] args) {
Game game = new Game();
game.start();
try {
Thread.sleep(1000);
} catch (Exception e) {
}
game.setIndex(-1);
System.out.println("change.....");
}
}
主线程修改后的值没有被子线程读取到,所以结果会是一个死循环
当使用volatile关键字修饰index变量之后, 程序可以正常退出
volatile 怎么保证有序性和可见性?
可见性:
volatile的两条实现原则:
- Lock前缀指令会引起处理器缓存会写到内存,
当对volatile变量进行写操作的时候,JVM会向处理器发送一条lock前缀的指令,将这个缓存中的变量回写到系统主存中 - 一个处理器的缓存回写到内存会导致其他处理器的缓存失效, 处理器使用嗅探技术保证内部缓存, 系统内存和其他处理器的缓存的数据在总线上保持一致。
综合上面两条实现原则,我们了解到:如果一个变量被volatile所修饰的话,在每次数据变化之后,其值都会被强制刷入主存。而其他处理器的缓存由于遵守了缓存一致性协议,也会把这个变量的值从主存加载到自己的缓存中。因此当有线程对变量进行修改之后, 其他线程读取到的都是修改之后的值; 这就保证了可见性;
有序性:
volatile 禁止了JVM的重排序, 禁止了重排序,就不存在有序性的问题了.
volatile能保证原子性么?
不能.