volatile是一个轻量级的锁(synchronized),如果一个变量使用volatile,则它比使用synchronized的成本更低,因为它不会引起线上上下文的切换和调度。
一个变量如果用volatile修饰了,则Java可以确保所有线程看到这个变量的值是一致的,如果某个线程对volatile修饰的共享变量进行更新,那么其他线程可以立马看到这个更新,这就是所谓的线程可见性。
注意:volatile不保证操作的原子性,但synchronized则可以保证。
volatile相对于synchronized稍微轻量些,在某些场合它可以替代synchronized,但是又不能完全取代synchronized,只有在某些场合才能够使用volatile。使用它必须满足如下两个条件:
1.对变量的写操作不依赖当前值;
2.该变量没有包含在具有其他变量的不变式中。
volatile经常用于两个两个场景:状态量标记、double check
double check示例:
public class Singleton {
private static volatile Singleton singleton = null;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
当然单例模式延迟初始化还可使用其他的方式,比如枚举、静态内部类。可以参考这篇文章:https://blog.csdn.net/goodlixueyong/article/details/51935526。
注意:使用volatile做双重检查只有在jdk1.5或之后的版本正常,之前的版本由于JMM(java内存模型)仍然是有问题的。