C# 单例模式的实现和性能对比

本文介绍了C#中单例模式的多种实现方式,包括非线程安全、简单的线程安全、双重验证的线程安全、不用锁的线程安全、完全延迟加载以及使用.NET4的`Lazy<T>`类型实现。分析了它们的线程安全性与性能差异,发现锁的使用会影响性能,而`Lazy<T>`实现虽稍慢但提供了延迟加载。总结建议一般情况下,方法二或方法六已足够使用,而方法四和五需要对C#有深入理解。
摘要由CSDN通过智能技术生成

简介

单例指的是只能存在一个实例的类(在C#中,更准确的说法是在每个AppDomain之中只能存在一个实例的类,它是软件工程中使用最多的几种模式之一。在第一个使用者创建了这个类的实例之后,其后需要使用这个类的就只能使用之前创建的实例,无法再创建一个新的实例。通常情况下,单例会在第一次被使用时创建。本文会对C#中几种单例的实现方式进行介绍,并分析它们之间的线程安全性和性能差异。

单例的实现方式有很多种,但从最简单的实现(非延迟加载,非线程安全,效率低下),到可延迟加载,线程安全,且高效的实现,它们都有一些基本的共同点:

. 单例类都只有一个private的无参构造函数
. 类声明为sealed(不是必须的)
. 类中有一个静态变量保存着所创建的实例的引用
. 单例类会提供一个静态方法或属性来返回创建的实例的引用(eg.GetInstance) 

几种实现

一. 非线程安全

//Bad code! Do not use!
public sealed class Singleton
{private static Singleton instance = null;private Singleton(){}public static Singleton instance{get{if (instance == null){instance = new Singleton();}return instance;}}
} 

这种方法不是线程安全的,会存在两个线程同时执行if (instance == null)并且创建两个不同的instance,后创建的会替换掉新创建的,导致之前拿到的reference为空。

二. 简单的线程安全实现

public sealed class Singleton
{private static Singleton instance = null;private static readonly object padlock = new object();Singleton(){}public static Singleton Instance{get{lock (padlock){if (instance == null){instance = new Singleton();}return instance;}}}
} 

相比较于实现一,这个版本加上了一个对instance的锁,在调用instance之前要先对padlock上锁,这样就避免了实现一中的线程冲突,该实现自始至终只会创建一个instance了。但是,由于每次调用Instance都会使用到锁,而调用锁的开销较大,这个实现会有一定的性能损失。

注意这里我们使用的是新建一个private的object实例padlock来实现锁操作,而不是直接对Singleton进行上锁。直接对类型上锁会出现潜在的风险,因为这个类型是public的,所以理论上它会在任何code里调用,直接对它上锁会导致性能问题,甚至会出现死锁情况。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值