volatile关键字在C语言和Java中都有,也就是说这个关键字应该是操作系统层次体现的特点,而不仅仅是语言层次的特性,我们应该上升到一个更高的层次来理解这个关键字。总的来说就是我们的数据最终存放在内存上,但是我们没有让cpu计算时直接从内存上进行存取,而是使用了诸如寄存器、一级缓存、二级缓存、java中内存模型还有线程内部缓存等,这些地方拷贝了同一份数据,所以会存在数据不同步的情况,那么volatile就是用来解决这个数据不同步的问题,在对volatile变量进行写操作时,会比写普通变量有两点不同,1是会将缓存写回内存,2是写回内存会导致其他cpu缓存的主存数据失效。应用程序访存都是经过操作系统的,所以是访问缓存还是主存对应用程序来说是完全透明的,无法直接操控,汇编是可以的,说明其实我们的应用程序还是在访问缓存的,只是高级语言已经替我们屏蔽了,那我们在高级语言里操作缓存的方式之一就是这个volatile关键字了。
我们先来说说volatile具有的特性,volatile修饰的变量具备可见性,但是对复合操作不保证原子性。这是最显著的特点,volatile的特性关系到Java内存模型以及编译器、处理器重排序等知识点,这些需要读者自己去花时间了解,我这里是作高度总结,不会讲述其中的细节原理。我们知道,编译器和处理器会对程序的执行作重排序操作以提高执行效率,对于单线程执行,重排序需要遵循as-if-serial规则,使单线程程序重排序执行和顺序执行的结果一样,对于多线程执行,Java规定了happen-before规则,一定程度上保证了多线程并发的安全,为Java程序员编写线程安全程序提供了极大便利,volatile应该就属于happen-before的规则之下,happen-before规定:运行时,对一个volatile域的写,一定happens-before后续对这个volatile域的读。其实这说的就是可见性,只是是从更贴近实现的角度说的。下面来说说volatile的实际应用场合。
1、状态标记
可能的伪代码如下:
volatile boolean stop = false;
public void stop(){
stop = true;
}
public void doWork(){
if (!stop){
......
}
}