volatile 与 synchronized 的区别

分类:并发

volatilesynchronized
可见性保证保证
有序性禁止相关的指令重排序保证
原子性只保证单次读写,count++ 这类复合操作不保证保证临界区整体的原子性
互斥没有有,同一时刻只有一个线程持有锁

为什么 volatile 不能用来计数

count++ 实际上是"读、加一、写回"三步。两个线程可能读到同一个旧值,各自加一后写回,结果只增加了一次。计数应使用 AtomicInteger,高并发累加可以用 LongAdder。

happens-before 的两条规则

双重检查锁定为什么要加 volatile

public class Singleton {
    private static volatile Singleton instance;
    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

instance = new Singleton() 大致分为分配内存、初始化对象、把引用赋给变量三步,后两步可能被重排序。没有 volatile 时,另一个线程可能在第一次判断时看到一个非空、但还没初始化完的对象。

怎么选