惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Hacker News: Ask HN
Hacker News: Ask HN
The Hacker News
The Hacker News
S
Security Affairs
T
Tor Project blog
N
News | PayPal Newsroom
V2EX - 技术
V2EX - 技术
Microsoft Security Blog
Microsoft Security Blog
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
P
Palo Alto Networks Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Vercel News
Vercel News
W
WeLiveSecurity
Y
Y Combinator Blog
TaoSecurity Blog
TaoSecurity Blog
MongoDB | Blog
MongoDB | Blog
Cloudbric
Cloudbric
大猫的无限游戏
大猫的无限游戏
Blog — PlanetScale
Blog — PlanetScale
G
GRAHAM CLULEY
博客园 - 聂微东
月光博客
月光博客
T
The Exploit Database - CXSecurity.com
C
Cyber Attacks, Cyber Crime and Cyber Security
Latest news
Latest news
H
Help Net Security
U
Unit 42
P
Privacy & Cybersecurity Law Blog
The GitHub Blog
The GitHub Blog
S
Securelist
The Last Watchdog
The Last Watchdog
Stack Overflow Blog
Stack Overflow Blog
H
Hacker News: Front Page
C
Check Point Blog
Schneier on Security
Schneier on Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
Arctic Wolf
P
Privacy International News Feed
WordPress大学
WordPress大学
T
Threatpost
博客园_首页
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Secure Thoughts
Simon Willison's Weblog
Simon Willison's Weblog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Jina AI
Jina AI

博客园 - 青玄鸟

.NET 中优雅处理 Server-Sent Events 请求取消 vue3.0 + ts 实现上传工厂(oss与cos) Dapr 订阅者参数无法正确反序列化问题 .NET 代码整洁手册 Blazor项目通过docker和nginx部署为静态站点的步骤 Moq mock 方法返回null空指针异常 基于接口隔离原则的依赖注入实现 HttpClient with Stream HttpClient partial update HttpClient 基本使用 值对象的封装 只读集合类型属性实现 适配器模式 模板模式 最少知识原则 抽象工厂 简单工厂、工厂方法、抽象工厂 工厂方法模式 使用 Visual Studio Code创建和执行T-SQL
单例模式
青玄鸟 · 2020-03-31 · via 博客园 - 青玄鸟

应用场景

业务概念上只适合在系统中保留一份的数据,比如系统的配置信息类适合设计为单例模式,还可以使用单例模式解决多个实例访问资源冲突的问题。

实现

饿汉式

    public class Singleton
    {
        static readonly Singleton instance = new Singleton();
        private Singleton()
        {

        }

        public static Singleton GetInstance()
        {
            return instance;
        }
    }

懒汉式

    public class Singleton
    {
        static Singleton instance = null;
        static readonly object lockObj = new object();
        private Singleton()
        {

        }

        public static Singleton GetInstance()
        {
            lock (lockObj)
            {
                if (instance==null)
                {
                    instance = new Singleton();
                }
            }
            return instance;
        }

    }

双重检测

    public class Singleton
    {
        static Singleton instance = null;

        static readonly object lockObj = new object();
        private Singleton()
        {

        }

        public static Singleton GetInstance()
        {
            if (instance==null)
            {
                lock (lockObj)
                {
                    if (instance==null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }

    }

简洁版双重检测,Lazy,Lazy是线程安全的,内部封装了需要的锁。

    public class Singleton
    {
        static Lazy<Singleton> singletonWrapper = null;
        private Singleton()
        {

        }

        public static Singleton GetInstance()
        {
            singletonWrapper = new Lazy<Singleton>(()=>new Singleton());
            return singletonWrapper.Value;
        }
    }

内部静态类

    public class Singleton
    {
        private Singleton()
        {

        }

        private static class SingletonHolder
        {
            public static readonly Singleton instance = new Singleton();
        }

        public static Singleton GetInstance()
        {
            return SingletonHolder.instance;
        }
    }

实现对比

  1. 饿汉式,在类加载期间就已经将instance静态类初始化好,所以instance实例的创建时线程安全的。不过饿汉式不支持延迟加载。

  2. 懒汉式,支持延迟加载,但是会导致频繁加锁、释放锁,以及并发度低的问题,频繁调用会产生性能瓶颈

  3. 双重检测,既支持延迟加载,又支持高并发。只要instance实例被创建之后,再调用GetInstance方法都不会进入到加锁的逻辑中。之所以会检查两次instance是否为null,是因为install为null,时,可能会有两个或者多个线程同时通过第一层检查,在一个线程创建完instance实例后,其他线程进入lock之内,不检查instance会再次创建实例。

  4. 内部静态类,既支持延迟加载,又支持高并发。延迟加载体现在外部单例类被加载时,并不会创建内部静态类,只有在调用GetInstance方法时,内部类才会被加载,这时才创建instance,内部静态类的实现比双重检测简单。

单例模式存在的问题

  1. 违背了基于接口而非实现编程,在发生变化时,应用到单例类的代码都需要修改,也违背了开闭原则

  2. 单例会隐藏类之间的依赖关系,通过参数声明的以来关系,查看函数定义就能很容易识别出来,单例类不需要显式创建,不需要依赖参数传递,直接调用,如果代码比较复杂,这种调用关系会非常隐蔽

  3. 单例对代码的可测试性不友好