单例模式: 定义 一个类有且仅有一个实例,并且自行实例化向整个系统提供。
《来自百科》 这些 概念和要点 是 了解 单例模式的 一些基本概念
private static Singleton instance; /// <summary> /// 把构造函数 声明 为 私有,这样就 阻止了 外界 对 这个类的new 操作 /// </summary> private Singleton() { } //此方法是获得 本类 实例 的 全局 唯一的访问点 public static Singleton GetInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
但 上面代码 在 多线程程序中, 多个线程同时访问getinstance();就可能造成创建 多个 实例。所以此时给进程 加一把锁 lock 来进行处理。
Lock 是确保 当一个线程 位于代码 的临界区时,另一个线程 不能进入临界区。如果其他线程 试图进入 临界区 ,则会 一直 处于 等待状态,知道 对象会被释放。
修改代码:
public class Singleton { private static Singleton instance; // 创建一个 静态只读的 进程 辅助对象 private static readonly object syncroot = new object(); /// <summary> /// 把构造函数 声明 为 私有,这样就 阻止了 外界 对 这个类的new 操作 /// </summary> private Singleton() { } //此方法是获得 本类 实例 的 全局 唯一的访问点 public static Singleton GetInstance() { //在同个 时刻,加入锁的 那部分程序 只有一个线程可以进入 lock (syncroot) { if (instance == null) { instance = new Singleton(); } } return instance; } }
不直接 lock (instance) 是因为 不知道 有没有创建过实例,所以只能 在 getinstance()时 加锁。
但是每次 调用 getinstance()时都要 进行 lock() 不好,所以应该在必要时进行lock();
引入双重锁定
public class Singleton { private static Singleton instance; // 创建一个 静态只读的 进程 辅助对象 private static readonly object syncroot = new object(); /// <summary> /// 把构造函数 声明 为 私有,这样就 阻止了 外界 对 这个类的new 操作 /// </summary> private Singleton() { } //此方法是获得 本类 实例 的 全局 唯一的访问点 public static Singleton GetInstance() { //先判断 实例是不是存在, 不存在 再 加锁 锁定 一个 线程 if (instance == null) { //在同个 时刻,加入锁的 那部分程序 只有一个线程可以进入 lock (syncroot) { //此时的 判断实例是不是为空 是 当 有两个 进程 AB 依次执行时, A执行完后 接着 执行B // 因为没有 实例的释放, 要进行 再次 判空 看是否已经 有实例产生了, // 这样 防止了产生多个实例 if (instance == null) { instance = new Singleton(); } } } return instance; } }
在实际的开发中 C# 与 公共 语言运行库 提供了 一种 静态 初始化 的 方法,这种方法不需要开发人员 显示的 编写线程安全代码 ,即可 解决多线程环境下不安全的
问题
public sealed class Singleton { //在第一次引用类的任何成员创建实例 公共语言运行库 负责处理变量初始化 private static readonly Singleton instance = new Singleton(); public static Singleton getinstance() { return instance; } }
由于这种方法 是在 自己 被加载时 就将自己 实例化, 所以形象的称为“ 饿汉式” 单例类 由于一加载就实例化 提前占用系统资源
前面 处理方式 是在 自己 第一次 被 引用时 才 实例化,所以称为“懒汉式 ” 单例类。 面临的更多是多线程 安全 问题 ,需要双向 锁定 才能解决
全局变量 和 单例 模式 的 区别:
全局变量 即对一个对象的静态引用,全局变量确实可以提供单例模式实现的全局访问这个功能,但是,它并不能保证您的应用程序中只有一个实例,同时,在编码规范中,也明确指出,应该要少用全局变量,因为过多的使用全局变量,会造成代码难读,还有就是全局变量并不能实现继承(虽然单例模式在继承上也不能很好的处理,但是还是可以实现继承的)而单例模式的话,其在类中保存了它的唯一实例,这个类,它可以保证只能创建一个实例,同时,它还提供了一个访问该唯一实例的全局访问点。
原文:http://www.cnblogs.com/lfyy/p/5128967.html