谈谈对volatile关键字的理解

1. volatile的特性

volatile是Java语言提供的一种轻量级的同步机制,用来确保将变量得更新操作通知到其它线程。具备三种特性:

  • 保证变量的可见性
  • 对于volatile修饰的变量进行单次读/写操作可以保证原子性,对于i++这样的多次操作不保证原子性
  • 防止指令重排(通过在指令序列中插入内存屏障来禁止特定类型的处理器重排序)。

2. volatile关键字和synchronized关键字的区别

区别可以从以下四点阐述:

  • volatile关键字是线程同步的轻量级实现,其性能比synchronized关键字好。但是volatile关键字只能修饰变量而synchronized关键字可以修饰方法以及代码块。synchronized关键字在JDK1.6之前是一种重量级锁,在1.6之后进行了一系列的优化(主要是为了减少获得锁和释放锁带来的性能消耗而引入偏向锁和轻量级锁使得效率有所提升),实际中使用synchronized的场景相对较多;
  • 多线程情况下访问volatile关键字修饰的变量不会造成阻塞,而synchronized关键字可能会造成阻塞;
  • volatile可以保证变量的可见性,但不能完全保证数据操作的原子性,而synchronized技能保证变量可见性也能保证原子性;
  • volatile关键字主要用于解决变量在多个线程之间的可见性问题,而synchronized关键字解决的是多个线程之间访问资源的同步性。

3. 使用volatile关键字的场景

单例模式(双检锁DCL)

public class Singleton {
    
    private volatile static Singleton singleton;
    
    private Singleton() {
    }
    
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

使用volatile关键字修饰singleton,防止指令重排。如果不加volatile关键字,则会出如下问题:在执行if (singleton == null)判断时,有可能singleton对象正在初始化的过程中还未完成,因此会通过双重检查,然后又进行一次singleton对象的初始化,从而导致出现多个实例。

原文地址:https://www.cnblogs.com/chiaki/p/13499714.html