<span>单例模式</span>

💛原文地址为https://www.cnblogs.com/haixiang/p/12063951.html,转载请注明出处!

简介

单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例

要求

只需要三部分即可保证只有一个实例

  • 不允许被外部类 new 对象
  • 在本类中创建对象
  • 对外提供接口调用创建好的对象

实现思路

针对上述三个条件我们用三种方式来保证这种要求

  • 构造方法私有化
  • 在本类中 new 一个本类对象
  • 创建一个 public 方法返回上步创建好的对象以供外部调用

懒汉式单例模式

这种方式在类创建的时候就实例化对象,不存在多线程问题,缺点是提前创建对象,若未被使用会造成资源浪费。

public class SingletonIns {

    private static SingletonIns singletonIns = new SingletonIns();
    
    private SingletonIns() {}
    
    public static SingletonIns getInstance() {
        return singletonIns;
    }
}

饿汉式单例模式

饿汉式单例优缺点与懒汉式正好相反,如果不作处理会有并发的问题,但是按需实例化,能避免资源被浪费的情况出现。

以下是最佳实践的例子

public class SingletonIns {
    private static volatile SingletonIns singletonIns = null;
    private SingletonIns() {}
    public static SingletonIns getInstance() {
        if (null == singletonIns) {
            synchronized (SingletonIns.class) {
                if (null == singletonIns) {
                    singletonIns = new SingletonIns();
                }
            }
        }
        return  singletonIns;
    }
}

以下这种方式效率较低,在jdk以前的版本中synchronized性能极差,后续有了自旋锁、偏量锁等优化才慢慢改善,现在仍然不建议这样使用单例模式

public class SingletonIns {
    private static SingletonIns singletonIns = null;
    private SingletonIns() {}
    public synchronized static SingletonIns getInstance() {
        if (null == singletonIns) {
            singletonIns = new SingletonIns();
        }
        return  singletonIns;
    }
}

以下这种方式存在线程安全的问题,例如a线程进入if判断,b线程已经进入2处,会导致实例化两个不同的对象

public class SingletonIns {
    private static SingletonIns singletonIns = null;
    private SingletonIns() {}
    public static SingletonIns getInstance() {
        if (null == singletonIns) { //1 有线程安全问题
            synchronized(SingletonIns.class) {
            	singletonIns = new SingletonIns();//2
            }
        }
        return  singletonIns;
    }
}

以下这种方式使用双重校验来避免上一种线程安全问题的出现,但是仍然存在线程安全问题。这是因为在线程执行到第1处的时候,代码读取到instance不为null时,instance引用的对象有可能还没有完成初始化

public class SingletonIns {
    private static SingletonIns instance = null;
    private SingletonIns() {}
    public SingletonIns getInstance() {
        if (null == instance) { //1
            synchronized(SingletonIns.class) {
                if(null == instance)
            	instance = new SingletonIns();//2
            }
        }
        return  instance;
    }
}

为什么会出现这样的问题呢?主要的原因是重排序。重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。
第2处的代码创建了一个对象,这一行代码可以分解成3个操作:

Copymemory = allocate();  // 1:分配对象的内存空间
ctorInstance(memory); // 2:初始化对象
instance = memory;  // 3:设置instance指向刚分配的内存地址

根源在于代码中的2和3之间,可能会被重排序。例如:

Copymemory = allocate();  // 1:分配对象的内存空间
instance = memory;  // 3:设置instance指向刚分配的内存地址
// 注意,此时对象还没有被初始化!
ctorInstance(memory); // 2:初始化对象java

这在单线程环境下是没有问题的,但在多线程环境下会出现问题:B线程会看到一个还没有被初始化的对象。
A2和A3的重排序不影响线程A的最终结果,但会导致线程B在B1处判断出instance不为空,线程B接下来将访问instance引用的对象。此时,线程B将会访问到一个还未初始化的对象。

重排序能够保证单线程的情况下,执行结果与按顺序执行结果一致,但是无法保证多线程下结果正确。所以我们需要使用volatile来修饰instance,来禁用重排序,保证线程安全

全部评论

相关推荐

时间线:&nbsp;1.4-1.5:&nbsp;boss&nbsp;牛客&nbsp;官网&nbsp;实习僧海投了两天,&nbsp;感觉确实没啥招人的啊,&nbsp;心里凉了一半.1.6:&nbsp;中午快手约面,&nbsp;下午字节hr飞书私聊约面,&nbsp;当时想着第一次面大厂感觉三个过一个一面就已经赢了.1.7:&nbsp;下午&nbsp;3点大厂处女面,&nbsp;哈哈面试官是重邮红岩的直接保送;&nbsp;5点快手一面,&nbsp;我说这个是我的第二次大厂面试,&nbsp;面试官问要是拿到字节和快手选择哪个,&nbsp;我说昨天看了一晚上快手百分百选快手哈哈哈.&nbsp;晚上5.30字节约二面,&nbsp;快手约二面,&nbsp;小红书约一面.1.8:&nbsp;下午2点快手二面,&nbsp;聊天面体验非常好(当天电话确认入职时间);&nbsp;4点字节二面这次不是校友了,&nbsp;然后有一个CSS实现switch效果的忘记属性咋写了,&nbsp;感觉危了;&nbsp;7.30&nbsp;问字节hr是不是挂了;&nbsp;9点开始小红书一面,&nbsp;难死我了,&nbsp;但我还是笑着面完了,&nbsp;然后卸载了小红书,&nbsp;但是过了一会会小红书hr约二面,&nbsp;遂下回来了字节约三面.1.9:&nbsp;下午2点字节三面,&nbsp;依旧聊天+算法,&nbsp;自己太菜了有一个写错了,&nbsp;面完感觉又危了;&nbsp;5点面小红书20min结束(offer审批);5.30又去问字节hr是不是挂了,&nbsp;hr小姐姐说干嘛用一个句式,&nbsp;我说手写题又又又没写出来😂,&nbsp;2min后约hr面;8.30&nbsp;快手offer总结,&nbsp;自己运气好遇到了好公司好部门好面试官,&nbsp;字节剪映&nbsp;快手电商&nbsp;小红书支付的面试体验都非常好,&nbsp;不会的题会带你一步一步思考,&nbsp;流程也非常快全部都是当天推进,&nbsp;小红书是以分钟为单位推进.&nbsp;&nbsp;面经以及细节等我慢慢整理,&nbsp;&nbsp;以及保佑所有的审批不要出问题,&nbsp;我是真怕最后全过了0offer😂bg:&nbsp;重邮&nbsp;大数据&nbsp;蓝山工作室&nbsp;一段非大厂实习
独角仙梦境:这是真👻了
找实习记录
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务