手记

设计模式之单例模式与线程安全问题

前言

单例模式分为“饿汉模式”与“懒汉模式”。今天我们来聊聊单例模式,特别是在多线程中我们需要特别注意。

饿汉模式

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;

    }

}

这种方式为单例模式的懒汉模式,只有在第一次调用的时候才会去初始化对象。这种情况在多线程情况下会出现非线程安全问题。那么我们就来解决懒汉模式的线程安全问题。

同步方法解决

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(双重检查)实现更细粒度的同步代码块。

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;

    }

}

那么说到这里就把单例模式介绍完了,上述问题中如果有什么错误的地方,请留言告诉我,我会第一时间修改,以防止误导读者。谢谢!

©著作权归作者所有:来自51CTO博客作者刺激乐天派的原创作品,如需转载,请注明出处,否则将追究法律责任


0人推荐
随时随地看视频
慕课网APP