1. 什么是单例模式?
对于一些对象,我们只需要其一个实例对象,比如说:线程池、缓存、注册表、日志对象等。如果这些对象创建了多个实例,会导致不必要的资源占用。
这个模式确保一个类只有一个实例,并提供一个全局访问点
2. 单例模式的实现方法(分为线程安全和线程不安全)
首先,我们先看一下如下的代码:
public class Singleton {
private static Singleton singleton = null;
public static Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
return singleton;
}
return singleton;
}
// other method
}
上述代码确实可以做到调用
getInstance()
返回的是同一个实例对象,但是有个问题:多线程情况下,多线程同时调用!该方法。会导致多个实例对象被创建。
下面用一张图来说明这个问题:
如果两个线程同时执行到箭头位置,则由于类中变量为null,所以同时判断为真,返回的是两个不同的实例对象。
那如何保证线程安全?
代码改成如下:
public synchronized static Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
return singleton;
}
return singleton;
}
或者
private static Singleton singleton = new Singleton();
public static Singleton getInstance(){
return singleton;
}
上述方法可以解决线程同步的问题,为了解决在 getInstance()
中的同步,我们可以使用“双重检查加锁”
private static volatile Singleton singleton = null;
public static Singleton getInstance(){
if (singleton == null ){
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton();
return singleton;
}
}
}
return singleton;
}
加上 volatile
可以保证该变量改变时,其他线程可以正确的感知并更新。这种方法首先检查实例是否被创建,如果没有创建,才进行同步。这样提高了多线程性能。