volatile保证内存可见性,禁止指令重排序(cpu的优化,保证结果一致的情况下对指令进行选择性执行),但同时,volatile不可保证操作的原子性
public class Volatile {
//volatile 内存可见性,禁止重排序
private /*volatile*/ boolean flag = true;
private void run(){
while(flag){
}
}
public static void main(String...args){
Volatile invoke = new Volatile();
new Thread(invoke::run).start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
invoke.flag = false;
}
}
上段代码运行时虚拟机不会被停止,因为线程运行时会将flag拷贝到自己的工作内存中进行操作,而在run方法中线程会不断地判断工作内存中flag的值,这时cpu处于忙碌状态,不会到主内存中将主线程修改过的flag值重新刷新到工作内存中,所以程序会一直运行。
如果使用volatile关键字,则保证了变量flag的可见性,当有线程修改了flag时,会通知其他的线程工作内存中的flag副本已过期,这样其他线程会去主内存中重新读取flag的值,这样程序就会停止。
而正是因为这样,所以volatile只保证了读取的值是可见的,但当有线程对flag进行写操作时,不能保证一致性,如果需要一致性,则需要进行上锁,即volatile是不能替代synchronized关键字的,只有当仅需要可见性而不需要原子性时可以使用volatile提高效率。