0
点赞
收藏
分享

微信扫一扫

【设计模式】创建型设计模式 - 单例模式

半夜放水 2022-02-10 阅读 52

文章目录


主要是划分两种,饱汉和饿汉。

一、饱汉设计

用的时候再创建(就会有线程安全问题需要处理)
三步:

  • 私有化构造函数
  • 私有化 静态对象
  • 创建 静态获取对象方法
public class SingleTon {

    private static SingleTon singleTon;

    private SingleTon(){};

    public static SingleTon getInstance(){
        if (singleTon == null){
            singleTon = new SingleTon();
        }
        return singleTon;
    }
}

改进 - 提高线程安全

添加关键字synchronized,加锁

public class SingleTon {

    private static SingleTon singleTon;

    private SingleTon(){};

    public static synchronized SingleTon getInstance(){
        if (singleTon == null){
            singleTon = new SingleTon();
        }
        return singleTon;
    }
}

再改进 - 锁的细粒度降低

public class SingleTon {

    private static SingleTon singleTon;

    private SingleTon(){};

    public static SingleTon getInstance(){
        if (singleTon == null){
            synchronized(SingleTon.class){
                singleTon = new SingleTon();
            }
        }
        return singleTon;
    }
}

还会有一定的问题,多线程访问的情况下,这个锁不能保证内存中对象唯一。当AB线程同时在第8行后,准备进入第9行,此时A拿到锁进去创建一个对象后释放锁,B还能拿着锁进去创建对象

再再改进 - DCL 双重检查锁定

public class SingleTon {

    private static SingleTon singleTon;

    private SingleTon(){};

    public static SingleTon getInstance(){
        if (singleTon == null){
            synchronized(SingleTon.class){
                if(singleTon == null){
                    singleTon = new SingleTon();
                }
            }
        }
        return singleTon;
    }
}

能在多线程情况下,保持高性能。
但!因为第11行创建对象的操作并不是原子性操作。因此还会有一定的风险

终极改进 volatile 关键字 - 禁止指令重排

因为singleTon= new SingTon()

public class SingleTon {

    private static volatile SingleTon singleTon;

    private SingleTon(){};

    public static SingleTon getInstance(){
        if (singleTon == null){
            synchronized(SingleTon.class){
                if(singleTon == null){
                    singleTon = new SingleTon();
                }
            }
        }
        return singleTon;
    }
}

二、饿汉设计

没有线程安全的问题(不管用不用,一直都在内存)

public class SingleTon {

    private static SingleTon singleTon = new SingleTon();

    private SingleTon(){};

    public static SingleTon getInstance(){
        return singleTon;
    }
}

三、如何选择

如果对象不大,且创建不复杂,直接用饿汉方式即可
其他情况则采用懒汉实现方式

举报

相关推荐

0 条评论