在《java并发编程实战》(Brian Geoetz等著童云兰译)这本书里有对volatile的说明,Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。
这段话没任何问题,但我很长时间以来都不敢记忆,因为我不理解这段话,怕这里有坑。之前在写c语言代码时,对在变量前加与不加volatile的情况进行了反汇编,可以从汇编代码下看出不加volatile时编译器的优化。详情可以看我前面发的《智能小车48:编译器对volatile优化了什么?》。而我不会得到Java的汇编代码,所以无法用这样的方式来证实编译器对valotile的优化。今天我参考一位同学的java代码,用实际的执行效果来证明volatile的作用。
代码思路是,一个对象里有一个共享boolean变量初始化为true,对象里有一个方法启动两个线程。一个线程把它改为false,另一个线程则是while(boolean); 就是说如果另一个线程检测到变量为false就能退出,否则就死循环。
代码如下:
我其中一次的执行结果如下图:
有的线程正常退出了死循环,有的没有,所以进程一直没有结束。
做为对比,再给boolValue变量前面加上volatile,多运行几次看看,还有问题么?没有吧。这就是volatile对变量的可见性的控制的效果。原理就是每次操作都写回内存,不会复用寄存器里的值。好了,遇到这个关键字,可以不心虚了。