3.单例模式------双检测锁机制的单例模式

前面介绍的懒汉式单例模式使用方法,在单线程的程序应用中是没有任何问题的,但是在多线程的程序中就会出现问题,当多个线程都进行if(instance == null)判断时,就会产生多个类的实例,这就违反了单例模式的原则,也不符合程序的需要,怎么办呢?对于多线程下的应用,可以增加synchronized()同步机制,示意代码如下:

public class Singleton{
    private static Singleton instance = null;
    pricate Singleton(){
        //.....
    }
    //增加同步机制
    public static synchronized Singleton getInstance(){
        if (instance == null){
            instance == new Singleton();
        }
        return instance;
    }
}

此时,将synchronized(同步)机制放在了获取实例的方法上,如果该程序在多个线程下执行,将会只产生一个该类的实例,达到了单例模式的需求,但是因为这种写法是将synchronized(同步)机制放在了获取实例的方法上,导致程序每获取一次实例,都将进入synchronized(同步)机制,如果在程序运行时,需要大量的获取该类的实例,这种方法将时非常低效的。还有另外一种写法,将synchronized(同步)机制放在产生实例的代码前。示意代码如下所示:

public class Singleton{
    private static Singleton instance = null;
    private Singleton(){
        //...
    }
    public static Singleton getInstance(){
        if(instance == null){
            synchronized(Singleton.class){//增加同步机制
                instance = new Singleton();
            }
        }
    }
}

这种写法避免了每次获取实例时,都进入sunchronized(同步机制),但是和最初的写法一样,采用这种写法则避免不了在多线程时,返回多个实例的问题,为此产生了新的写法Double-checked locking(双检测锁)机制,示意代码如下:

    public class Singleton{
        private static Singleton instance = null;
        private Singleton(){
            //..
        }
        Public static Singleton getInance(){
            if (instance == null){
                Synchronized(Singleton.Class)//增加同步机制
                if (instance == null){//对是否为null再次进行判断
                    instance = new Singleton();
                }
            }   
            return instance;
        }
    }

这种方式下,只有第一次创建实例时,才进入synchronized(同步)机制,以后因为实例已经创建,将不会再进入synchronized同步机制。因此这种做法,满足了在多线程条件下单例模式的应用,其实最简单的做法,还是最开始的那种,直接new一个该类的实例,示意代码如下:

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

猜你喜欢

转载自blog.csdn.net/xiaohaopei/article/details/82226751