zoukankan      html  css  js  c++  java
  • 单例模式

    单例

      1.饿汉式单例

        优点:没有加锁,执行效率更高

             缺点:类加载的时候就初始化,不管用否都占着空间,如果项目中存在大量的单例对象,则会浪费内存空间

        

      2.懒汉式单例

        优点:被外部类调用时,内部才会加载

        

          存在线程安全,当有多个线程同时访问时,返回多个实例,违反了单例对象原则

        

         添加了synchronized关键字,当有大量线程同时访问时,cpu分配压力上升,造成阻塞,造成性能下降

        

         双重检查锁 

        这里的写法将同步放在了方法里面的第一个非空判断之后,这样可以确保对象不为空的时候不会被阻塞,但是第二个非空判断的意义是什么呢?我们假设线程A首先获得锁,进入了第3行,还没有释放锁的时候,线程B又进来了,这时候因为线程还没有执行对象初    始化,所以判空成立,会进入第2行等待获得锁,这时候当线程A释放锁之后,线程B会进入到第3行,这时候因为第二个判空判断对象不为空了,所以就会直接返回,如果没有第2个判空,这时候就会产生新的对象了,所以需要两次判空!

    大家可能注意到这里的变量定义上加了volatile关键字,为什么呢?这是因为DCL在可能会存在失效的情况:
    第4行代码:lazySingleton = new LazyDoubleCheckSingleton();
    大致存在以下三步:
    (1)、分配内存给对象
    (2)、初始化对象
    (3)、将初始化好的对象和内存地址建立关联(赋值)
    而这3步由于CPU指令重排序,不能保证一定按顺序执行,假如线程A正在执行new的操作,第1步和第3步都执行完了,但是第2步还没执行完,这时候线程B进入到方法中的第1行代码,判空不成立,所以直接返回了对象,而这时候对象并没有初始化完全,所以就会报错了,解决这个问题的办法就是使用volatile关键字,禁止指令重排序(jdk1.5之后),保证按顺序执行上面的三个步骤

        

         使用了内部类的特性,LazyHolder里面的内容等到外面调用时才执行,可以被反射或者序列化破坏单例

        

        

         

      3.注册式单例

        注册式单例是将所有的对象保存到某一个地方,通过唯一的标识符获取对应的单例对象

        

         

           4.ThreadLacal式单例

        ThreadLacal不能保证创建对象的全局唯一性,但是可以保证单个线程中对象的唯一性

        

         

  • 相关阅读:
    C#进阶之路(五):Linq初识
    C#进阶之路(四):拉姆达
    SQL夯实基础(五):索引的数据结构
    SQL夯实基础(四):子查询及sql优化案例
    SQL夯实基础(三):聚合函数详解
    C#进阶之路(三):深拷贝和浅拷贝
    SQL夯实基础(二):连接操作中使用on与where筛选的差异
    前端面试题整理—HTML/CSS篇
    CSS盒模型
    node的优缺点及应用场景
  • 原文地址:https://www.cnblogs.com/wanglu1991/p/15684508.html
Copyright © 2011-2022 走看看