1、非线程安全(经典模式),但没有考虑线程安全,在多线程时可能会出问题,不过还从没看过出错的现象。

  1. /// <summary>
  2. /// 单例模式的实现
  3. /// </summary>
  4. public class Singleton
  5. {
  6. // 定义一个静态变量来保存类的实例
  7. private static Singleton uniqueInstance;
  8.  
  9. // 定义私有构造函数,使外界不能创建该类实例
  10. private Singleton()
  11. {
  12. }
  13.  
  14. /// <summary>
  15. /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
  16. /// </summary>
  17. /// <returns></returns>
  18. public static Singleton GetInstance()
  19. {
  20. // 如果类的实例不存在则创建,否则直接返回
  21. if (uniqueInstance == null)
  22. {
  23. uniqueInstance = new Singleton();
  24. }
  25. return uniqueInstance;
  26. }
  27. }

2、简单安全线程

  1. /// <summary>
  2. /// 单例模式的实现
  3. /// </summary>
  4. public class Singleton
  5. {
  6. // 定义一个静态变量来保存类的实例
  7. private static Singleton uniqueInstance;
  8.  
  9. // 定义一个标识确保线程同步
  10. private static readonly object locker = new object();
  11.  
  12. // 定义私有构造函数,使外界不能创建该类实例
  13. private Singleton()
  14. {
  15. }
  16.  
  17. /// <summary>
  18. /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
  19. /// </summary>
  20. /// <returns></returns>
  21. public static Singleton GetInstance()
  22. {
  23. // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
  24. // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
  25. // lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
  26. lock (locker)
  27. {
  28. // 如果类的实例不存在则创建,否则直接返回
  29. if (uniqueInstance == null)
  30. {
  31. uniqueInstance = new Singleton();
  32. }
  33. }
  34.  
  35. return uniqueInstance;
  36. }
  37. }

上面这种解决方案确实可以解决多线程的问题,但是上面代码对于每个线程都会对线程辅助对象locker加锁之后再判断实例是否存在,对于这个操作完全没有必要的,因为当第一个线程创建了该类的实例之后,后面的线程此时只需要直接判断(uniqueInstance==null)为假,此时完全没必要对线程辅助对象加锁之后再去判断,所以上面的实现方式增加了额外的开销,损失了性能,为了改进上面实现方式的缺陷,我们只需要在lock语句前面加一句(uniqueInstance==null)的判断就可以避免锁所增加的额外开销,这种实现方式我们就叫它 “双重锁定”,下面是具体实现代码:

3、尝试线程安全(双重锁定)

  1. /// <summary>
  2. /// 单例模式的实现
  3. /// </summary>
  4. public class Singleton
  5. {
  6. // 定义一个静态变量来保存类的实例
  7. private static Singleton uniqueInstance;
  8.  
  9. // 定义一个标识确保线程同步
  10. private static readonly object locker = new object();
  11.  
  12. // 定义私有构造函数,使外界不能创建该类实例
  13. private Singleton()
  14. {
  15. }
  16.  
  17. /// <summary>
  18. /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
  19. /// </summary>
  20. /// <returns></returns>
  21. public static Singleton GetInstance()
  22. {
  23. // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
  24. // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
  25. // lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
  26. // 双重锁定只需要一句判断就可以了
  27. if (uniqueInstance == null)
  28. {
  29. lock (locker)
  30. {
  31. // 如果类的实例不存在则创建,否则直接返回
  32. if (uniqueInstance == null)
  33. {
  34. uniqueInstance = new Singleton();
  35. }
  36. }
  37. }
  38. return uniqueInstance;
  39. }
  40. }

4、饿汉模式(这种模式的特点是自己主动实例。)

  1. public sealed class Singleton
  2. {
  3. private static readonly Singleton instance=new Singleton();
  4.  
  5. private Singleton()
  6. {
  7. }
  8.  
  9. public static Singleton GetInstance()
  10. {
  11. return instance;
  12. }
  13. }

5、不完全lazy,但是线程安全且不用锁。

  1. public sealed class Singleton
  2. {
  3. private static readonly Singleton instance = new Singleton();
  4.  
  5. // 显示的static 构造函数
  6. //没必要标记类型 - 在field初始化以前
  7. static Singleton()
  8. {
  9. }
  10.  
  11. // 定义私有构造函数,使外界不能创建该类实例
  12. private Singleton()
  13. {
  14. }
  15.  
  16. public static Singleton Instance
  17. {
  18. get
  19. {
  20. return instance;
  21. }
  22. }
  23. }

6、完全延迟实例化

  1. public sealed class Singleton
  2. {
  3. private Singleton()
  4. {
  5. }
  6.  
  7. public static Singleton Instance { get { return Nested.instance; } }
  8.  
  9. private class Nested
  10. {
  11. // Explicit static constructor to tell C# compiler
  12. // not to mark type as beforefieldinit
  13. static Nested()
  14. {
  15. }
  16.  
  17. internal static readonly Singleton instance = new Singleton();
  18. }
  19. }

7、使用 .NET 4's Lazy<T> 类型

  1. public sealed class Singleton
  2. {
  3. private static readonly Lazy<Singleton> lazy =
  4. new Lazy<Singleton>(() => new Singleton());
  5.  
  6. public static Singleton Instance { get { return lazy.Value; } }
  7.  
  8. private Singleton()
  9. {
  10. }
  11. }

详细内容介绍见网址:http://csharpindepth.com/Articles/General/Singleton.aspx#unsafe

C# 语句中的各种单例模式代码的更多相关文章

  1. SQL语句在查询分析器中可以执行,代码中不能执行

    问题:SQL语句在查询分析器中可以执行,代码中不能执行 解答:sql中包含数据库的关键字,将关键字用[]括起来,可以解决. 后记:建数据库的时候尽量避免使用关键字. 例子: sql.Format(&q ...

  2. java中异常抛出后代码还会继续执行吗

    今天遇到一个问题,在下面的代码中,当抛出运行时异常后,后面的代码还会执行吗,是否需要在异常后面加上return语句呢? public void add(int index, E element){ i ...

  3. LINQ语句中的.AsEnumerable() 和 .AsQueryable()的区别

    LINQ语句中的.AsEnumerable() 和 .AsQueryable()的区别 在写LINQ语句的时候,往往会看到.AsEnumerable() 和 .AsQueryable() .例如: s ...

  4. 【转】Java中try catch finally语句中含有return语句的执行情况(总结版)

    Java中try catch finally语句中含有return语句的执行情况(总结版) 有一点可以肯定,finally块中的内容会先于try中的return语句执行,如果finall语句块中也有r ...

  5. java中异常抛出后代码是否会继续执行

    为了回答这个问题,我编写了几段代码测试了一下,结果如下:  代码1:throw new Exception("参数越界");   System.out.println(" ...

  6. MySql的like语句中的通配符:百分号、下划线和escape

      MySql的like语句中的通配符:百分号.下划线和escape   %:表示任意个或多个字符.可匹配任意类型和长度的字符. Sql代码 select * from user where user ...

  7. [转]sql语句中出现笛卡尔乘积 SQL查询入门篇

    本篇文章中,主要说明SQL中的各种连接以及使用范围,以及更进一步的解释关系代数法和关系演算法对在同一条查询的不同思路. 多表连接简介 在关系数据库中,一个查询往往会涉及多个表,因为很少有数据库只有一个 ...

  8. Sqlserver 存储过程中结合事务的代码

    Sqlserver 存储过程中结合事务的代码  --方式一 if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[ ...

  9. 向已写好的多行插入sql语句中添加字段和值

    #region 添加支款方式--向已写好的多行插入sql语句中添加字段和值 public int A_ZhifuFS(int diqu) { ; string strData = @"SEL ...

随机推荐

  1. linux查看cpu个数,线程数及cpu型号

    1.查看CPU逻辑id grep 'physical id' /proc/cpuinfo | sort -u physical id : 0physical id : 1 2.查看物理CPU个数 $ ...

  2. Hibernate查询操作

    操作前需要创建好Hibernate项目,创建项目,可参考:http://www.cnblogs.com/zhaojinyan/p/9336174.html 一下的例子是从其他贴子粘过来的(知识无国界! ...

  3. Go 初体验 - 令人惊叹的语法 - defer.4 - defer 对宿主函数返回值的影响

    defer 函数可以影响宿主函数的返回值 看代码: 调用: 输出: 结果又让人意外了. coo1:因为传引用,return 时 i = 100, return 返回的也是 100,return 执行之 ...

  4. Android开发中使用Intent跳转到系统应用中的拨号界面、联系人界面、短信界面

    现在开发中的功能需要直接跳转到拨号.联系人.短信界面等等,查找了很多资料,自己整理了一下. 首先,我们先看拨号界面,代码如下: Intent intent =new Intent(); intent. ...

  5. js 清空html input file的值

    在做上传图片预览时,利用input onchange事件触发函数,但是type=file时,一定记得新建要清空原来的图片,因为原来的图片还存在在input里面,再选重复的图片没有change,故不会触 ...

  6. Java内存模型学习笔记

    Java内存模型(JMM):描述了java程序中各种变量(线程共享变量)的范根规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节.共享变量就是指一个线程中的变量在其他线程中也是可见 ...

  7. SpringBootsad整合EhCache做缓存处理

    轻量级的缓存框架Ehcache实现其功能.从以下几点切入: 什么是EhCache? 它和redis.membercache比较有什么优势? 和SpringBoot怎么整合? 实现机制? 有哪些坑? E ...

  8. ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

    centos7.5 使用into outfile备份失败 问题: mysql> select * from world.city into outfile '/tmp/world_city.da ...

  9. idea使用svn报错

    第一种情况:idea没有安装svn. 选择file→settings→plugins,在右侧框中搜索"SVN"(有的是subversion),选中搜索出来的东西,然后点击下面的in ...

  10. CSS【05】:CSS三大特性

    继承性 作用:给父元素设置一些属性,子元素也可以使用,这个我们就称之为继承性 示例代码: <style> div { color: red; } </style> <di ...