天天看点

单例模式的写法

单例模式的七种写法

  1. 懒汉,线程不安全
  2. 懒汉,线程安全
  3. 饿汉
  4. 静态内部类(推荐)
  5. 枚举(推荐)
  6. 双重校验锁
  7. CAS(推荐)

1.懒汉,线程不安全

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

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

2.懒汉,线程安全

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

3.饿汉

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
} 
           

4.静态内部类

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
} 
           

5.枚举

public enum Singleton {  
    INSTANCE;   
} 
           

6.双重校验锁

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;  
    }  
}  
           

7.CAS

CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。

用CAS的好处在于不需要使用传统的锁机制来保证线程安全,CAS是一种基于忙等待的算法,依赖底层硬件的实现,相对于锁它没有线程切换和阻塞的额外消耗,可以支持较大的并行度。

CAS的一个重要缺点在于如果忙等待一直执行不成功(一直在死循环中),会对CPU造成较大的执行开销。

public class SingletonCAS {

    private static final AtomicReference<SingletonCAS> instance = new AtomicReference<>();

    private SingletonCAS() {
    }

    public static SingletonCAS getInstance() {
        for (; ; ) {
            SingletonCAS singletonCAS = instance.get();
            if (null != singletonCAS) {
                return singletonCAS;
            }
            singletonCAS = new SingletonCAS();
            if (instance.compareAndSet(null, singletonCAS)) {
                return singletonCAS;
            }
        }
    }
}
           

继续阅读