• 几种单例模式总结


    个人博客地址https://home.cnblogs.com/u/wdfwolf3/。转载注明出处,谢谢。

      面试被要求写一个单例模式,想不起来双重锁的写法,就写了一个普通的饿汉模式。简单问题没答好,面试减去很多分数。回来翻看笔记,重新过了一遍,在博客中整理记录一下。

    1.懒汉式,线程不安全

    public class Lazy {
        private static Lazy instance;
        private Lazy(){}
    
        public static Lazy getInstance() {
            if (instance == null)
                instance = new Lazy();
            return instance;
        }
    }

    2.懒汉式,线程不安全

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

    3.饿汉式,线程安全

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

    4.双重校验锁,线程安全

      由于线程安全的懒汉式在任何时候只能有一个线程调用 getInstance() 方法,但是同步操作只需要在第一次创建单例实例对象时才被需要,所以它并不高效。这就出现了双重检验锁来解决这个问题。为什么在同步块内要检验两次,因为可能会有多个线程一起进入同步块外的 if,如果在同步块内不进行二次检验的话,阻塞的线程获得锁之后又会new一个新的对象,就会生成多个实例了。

    public class DoubleLock {
        private volatile static DoubleLock instance;
    
        private DoubleLock() {
        }
    
        public static DoubleLock getSingleton() {
            if (instance == null)
                synchronized (DoubleLock.class) {
                    if (instance == null)
                        instance = new DoubleLock();
                }
            return instance;
        }
    }

      这里对instance使用了volatile关键字,主要是用它的禁止指令重排序功能。new Singleton()并非是一个原子操作,在 JVM 中做了下面 3 件事情,

      a.给 instance 分配内存

      b.调用 Singleton 的构造函数来初始化成员变量

      c.将instance对象指向分配的内存空间(执行完这步 instance 就为非 null 了)

      JVM可能将语句c优化到语句b之前,当一个线程执行完c没有执行b,然后释放锁,另外一个线程获得锁,此时判断instance!=null,直接返回,那就会出错。

    5.静态内部类,线程安全

    public class Inner {
        private static class SingletonHolder {
            private static final Inner INSTANCE = new Inner();
        }
    
        private Inner() {
        }
    
        public static final Inner getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }

    6.枚举,线程安全

    public enum SingletonEnum {
        INSTANCE;
    }

     

    1、懒汉式,线程不安全

  • 相关阅读:
    RabbitMQ官方教程四 Routing(GOLANG语言实现)
    RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现)
    RabbitMQ官方教程二 Work Queues(GOLANG语言实现)
    RabbitMQ官方教程一Hello World(GOLANG语言实现)
    etcd学习之安装与命令
    docker安装consul集群
    golang实现无限级菜单(beego框架下)
    beego框架(golang)学习过滤器(实现restful请求)
    beego框架(golang)学习验证码
    九 Android基本知识介绍
  • 原文地址:https://www.cnblogs.com/wdfwolf3/p/7495524.html
Copyright © 2020-2023  润新知