单例模式分为“饿汉模式”与“懒汉模式”。今天咱们来聊聊单例模式,特别是在多线程中咱们须要特别注意。安全
class Singleton{ private static Singleton singleton = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return singleton; } }
这种模式称之为单例模式的饿汉模式。该模式是线程安全的。多线程
class LazySingleton{ private static LazySingleton lazySingleton; private LazySingleton(){} public static LazySingleton getInstance(){ if(lazySingleton == null){ lazySingleton = new LazySingleton(); } return lazySingleton; } }
这种方式为单例模式的懒汉模式,只有在第一次调用的时候才会去初始化对象。这种状况在多线程状况下会出现非线程安全问题。那么咱们就来解决懒汉模式的线程安全问题。ide
class LazySingleton{ private static LazySingleton lazySingleton; private LazySingleton(){} synchronized public static LazySingleton getInstance(){ if(lazySingleton == null){ lazySingleton = new LazySingleton(); } return lazySingleton; } }
使用synchronized关键字把get方法设置为同步方法,能够解决线程安全问题,可是效率低是一个问题,那么咱们考虑优化一下这个效率,咱们能够使用同步代码块,由于咱们只是在初始化处会出现线程安全问题。优化
class LazySingleton{ private static LazySingleton lazySingleton; private LazySingleton(){} public static LazySingleton getInstance(){ synchronized(LazySingleton.class) { if (lazySingleton == null) { lazySingleton = new LazySingleton(); } } return lazySingleton; } }
同步代码块也能够解决线程安全问题,可是上面的方式其实跟同步方法效率上没有什么很大不一样。咱们关键的同步代码实际上是lazySingleton = new LazySingleton();只要给它加上同步标识就能够,可是这样会有一个问题就是多个线程判断了须要初始化该类实例,但只能有一个操做,后面的阻塞,这个时候一但前面线程实例化完后,后面的线程又会实例化,因此咱们须要进行再次的检查,判断是否已经实例化了,这就是DCL(双重检查)实现更细粒度的同步代码块。线程
class LazySingleton{ private static LazySingleton lazySingleton; private LazySingleton(){} public static LazySingleton getInstance(){ if(lazySingleton == null) { synchronized (LazySingleton.class) { if (lazySingleton == null) { lazySingleton = new LazySingleton(); } } } return lazySingleton; } }
那么说到这里就把单例模式介绍完了,上述问题中若是有什么错误的地方,请留言告诉我,我会第一时间修改,以防止误导读者。谢谢!code