单例模式的七种写法
-
懒汉,线程不安全
-
懒汉,线程安全
-
饿汉
-
静态内部类(推荐)
-
枚举(推荐)
-
双重校验锁
-
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;
}
}
}
}