饿汉式单例与懒汉式单例的C#实现
来源:互联网 发布:php 服务器基础知识 编辑:程序博客网 时间:2024/06/06 02:58
本文将介绍如何使用C#语言实现饿汉式单例与懒汉式单例,并分析饿汉式单例与懒汉式单例的优缺点。
1. 饿汉式单例类
饿汉式单例类(Eager Singleton)是实现起来最容易的单例类,饿汉式单例类结构图如图1所示。
图1 饿汉式单例类图
从图1中可以看出,由于在定义静态变量的时候实例化单例类,因此在类加载时单例对象就已创建,代码如下:
class EagerSingleton { private static EagerSingleton instance = new EagerSingleton(); private EagerSingleton() { } public static EagerSingleton GetInstance() { return instance; }}
当类被加载时,静态变量instance 会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建。
2. 懒汉式单例类与双重检查锁定
与饿汉式单例类相同之处是,懒汉式单例类(Lazy Singleton)的构造函数也是私有的。与饿汉式单例类不同的是,懒汉式单例类在第一次被引用时将自己实例化,在懒汉式单例类被加载时不会将自己实例化。懒汉式单例类结构图如图2所示。
图2 懒汉式单例类图
从图2可以看出,在懒汉式单例类中,不是在定义静态变量时实例化单例类,而是在第一次调用静态工厂方法时实例化单例类。
但是懒汉式单例存在一个很严重的问题:如果在高并发、多线程环境下实现懒汉式单例类,在某一时刻可能会有多个线程需要使用单例对象,即会有多个线程同时调用GetInstance()方法,可能会造成创建多个实例对象,这将违背单例模式的设计意图。为了防止生成多个单例对象,需要使用C#语言中的lock关键字,lock关键字锁定的代码片段称之为临界区,可以确保当一个线程位于代码的临界区时,另一个线程不能进入临界区。如果其他线程试图进入锁定的代码,则将一直等待,直到该对象被释放为止。修改之后的懒汉式单例类代码如下:
class LazySingleton { private static LazySingleton instance = null; //程序运行时创建一个静态只读的辅助对象 private static readonly object syncRoot = new object(); private LazySingleton() { } public static LazySingleton GetInstance() { //第一重判断,先判断实例是否存在,不存在再加锁处理 if (instance == null) { //加锁的程序在某一时刻只允许一个线程访问 lock(syncRoot) { //第二重判断 if(instance==null) { instance = new LazySingleton(); //创建单例实例 } } } return instance; }}
在上面给出的懒汉式单例类实现代码中,对静态工厂方法GetInstance()中创建单例对象的代码进行了加锁,由于在调用时无法确定该单例对象是否已创建,因此需要使用辅助对象syncRoot来进行代码锁定。为了不影响程序的性能,此处只锁定创建单例对象的代码,并未锁定整个方法。如果实例存在则直接返回,如果实例未创建则加锁后再创建。
为了更好地对单例对象的创建进行控制,此处使用了一种被称之为双重检查锁定(Double-CheckLocking)的双重判断机制。在双重检查锁定中,当实例不存在且同时有两个线程调用GetInstance()方法时,它们都可以通过第一重“instance==null”判断,然后由于lock锁定机制,只有一个线程进入lock中执行创建代码,另一个线程处于排队等待状态,必须等待第一个线程执行完毕后才可以进入lock锁定的代码,如果此时不进行第二重“instance==null”判断,第二个线程并不知道实例已经创建,将继续创建新的实例,还是会产生多个单例对象,违背单例模式的设计思想,因此需要进行双重检查。
3. 饿汉式单例类与懒汉式单例类比较
饿汉式单例类在类被加载时就将自己实例化,它的优点在于无须考虑多个线程同时访问的问题,可以确保实例的唯一性;从调用速度和反应时间角度来讲,由于单例对象一开始就得以创建,因此要优于懒汉式单例。但是无论系统在运行时是否需要使用该单例对象,由于在类加载时该对象就需要创建,因此从资源利用效率角度来讲,饿汉式单例不及懒汉式单例,而且在系统加载时由于需要创建饿汉式单例对象,加载时间可能会比较长。
懒汉式单例类在第一次使用时创建,无须一直占用系统资源,实现了延迟加载,但是必须处理好多个线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过双重检查锁定等机制进行控制,这将导致系统性能受到一定影响。
Java程序员可进一步阅读:确保对象的唯一性——单例模式 (三)与 确保对象的唯一性——单例模式 (四)
【作者:刘伟 http://blog.csdn.net/lovelion】
- 饿汉式单例与懒汉式单例的C#实现
- 饿汉式单例与懒汉式单例的C#实现
- 饿汉式单例与懒汉式单例的C#实现
- 饿汉式单例与懒汉式单例的讨论
- 饿汉式单例与懒汉式单例的讨论
- 饿汉式与懒汉式单例模式的区别
- 另一种实现“饥汉”与“懒汉”
- 单例Singleton的“懒汉式”与“饿汉式”实现方法
- Java 懒汉式单例 饿汉式单例
- 懒汉式单例和饿汉式单例
- C++实现懒汉式单例模式
- 单例模式(3)- 饿汉式单例与懒汉式单例的讨论
- 确保对象的唯一性——单例模式 (三):饿汉式单例与懒汉式单例
- 单例懒汉式的另一种实现
- 懒汉式单例和饿汉式单例优缺点
- 饿汉式单例和懒汉式单例比较
- 懒汉式单例模式和饿汉式单例模式的区别
- 懒汉式单例模式和饿汉式单例模式的详解
- OK6410裸机程序---hello world
- linux下配置jdk环境变量以及查看java版本
- 爬楼梯
- 五款ASP.NET图表控件优缺分析(上):Ms Chart和TeeChart
- Android 数字签名学习笔记
- 饿汉式单例与懒汉式单例的C#实现
- 线程
- 微生物增值
- Android网络连接处理学习笔记
- Calendar的使用
- Hdu 4292 Food
- 徐小明:探寻股市下跌的真正原因
- C++果然还是有一个模版写起来要舒服点
- ERP权威文档翻译第二天