单例模式的安全写法

要想知道怎么写单例模式,那么必须得知道什么是单例模式。**单例模式是一种设计模式,它确保某个类只有一个实例,并且提供一个全局访问该实例的方法。单例模式不会创建实例副本,而是返回对已创建实例的引用。单例模式的创建可以分为两类。第一类是饿汉式单例模式,它在类加载时就创建了唯一的实例对象,并在全局范围内提供访问点。第二类是懒汉式单例模式,它在首次使用时才创建实例对象,以节省资源。**需要注意的是,懒汉式单例模式在多线程环境下需要考虑线程安全性。

复制代码
class Student2{
    private static Student2 student = new Student2();//饿汉模式
    private Student2(){
        ;
    }
    public static Student2 getStudent(){
        return student;
    }
}

因为要在使用时创建,那么就应该在获取的时候创建,并且获取时,得先判断,是否已经创建好了,如果没有的话,则就是首次调用,得创建实例,如果有的话,就应该使用创建好的。

复制代码
class Student3{
    private static Student3 student3 = null;
    private static Object locker = new Object();
    private Student3(){}
    public static Student3 getStudent3(){
        if (student3 == null) {student3 = new Student3();}
        return student3;
    }
}

咋看没有问题,实际问题很大。如果有多个线程同时使用该方法,这不就是多个线程同时修改同一个变量的问题吗?那么是否会因为都判定为是首次创建,而导致创建了多个实例呢?答案不言而喻。为了保证线程安全,因此得需要锁。那么就可以这样做:

复制代码
class Student3{
    private static Student3 student3 = null;
    private static Object locker = new Object();
    private Student3(){}
    public static Student3 getStudent3(){
        synchronized (locker){
            if (student3 == null) {student3 = new Student3();}
        }
        return student3;
    }
}

这样虽然解决了线程安全问题,不过每次判定是否需要创建时,都需要进入锁中,进入就会导致阻塞。倘若已经不是首次调用了,那么这个代码就会带来不小的开销。为什么呢?因为如果不是第一次使用了,那么就不需要创建了,也就不需要修改变量,因此就算此时没加锁并且有多个线程来使用该方法,也不会造成线程安全问题。不过因为此时仍然有锁,这就导致多线程时使用该方法会有线程在这堵塞,而且频繁的加锁解锁也会造成不必要的开销,因此得解决这个问题,要想解决这个问题,就必须进行再一次的判定来决定是否需要加锁,那么是否需要加锁的条件是什么呢?肯定时是否是第一次使用该方法啊,如果是的话,就需要加锁,如果不是,就不需要加锁并且可以直接返回该实例,同时不能确定这里是否存在内存可见性问题,因此最好加上volatile,因此代码可以如此的该:

复制代码
class Student3{
    private static volatile Student3 student3 = null;
    private static Object locker = new Object();
    private Student3(){}
    public static Student3 getStudent3(){
        if (student3 == null){//判断是否需要加锁
            synchronized (locker){
                if (student3 == null) {student3 = new Student3();}//判断
            }
        }
        return student3;
    }
}
相关推荐
2301_777998342 天前
C++ 单例模式详解:饿汉、懒汉,以及“对象”和“对象指针”到底有什么区别
开发语言·c++·单例模式
breeze jiang5 天前
JavaScript 单例模式:用静态属性保证 Popup 只创建一次
开发语言·javascript·单例模式
meilindehuzi_a5 天前
WebGPU DeepSeek项目实战(二):用单例模式加载Tokenizer并转发下载进度
单例模式·typescript·react
啦啦啦啦啦zzzz15 天前
设计模式:单例模式和工厂模式
c++·单例模式·设计模式·工厂模式
空杆推不起15 天前
金融数仓标准化:信贷业务 ODS/DWD/DWS/ADS/DIM 全层级建模指南
单例模式·金融
芝士熊爱编程23 天前
创建型模式-单例模式
java·单例模式·设计模式
张小姐的猫25 天前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
zjun100125 天前
C++:单例模式
c++·单例模式
ttod_qzstudio1 个月前
【软考设计模式】单例模式:唯一实例的管控与线程安全精讲
单例模式·设计模式
geovindu1 个月前
java: Singleton Pattern
java·开发语言·后端·单例模式·设计模式·创建型模式