三种方式构建C#单例模式
/// <summary>
/// 双检锁实现单例
/// </summary>
public sealed class SingletonDoubleCheck
{
//s_lock对象是实现线程安全所需要的,定义这个对象时,我们假设创建单例对象的代价高于创建一个System.Object对象
//并假设可能根本不需要创建单例对象,否则,更经济、更简单的做法是在一个类构造器中创建单例对象
private static Object s_lock = new Object(); //这个字段引用一个单例对象
private static SingletonDoubleCheck s_value = null; //私有构造器阻止这个类外部的任何代码创建实例
private SingletonDoubleCheck()
{ } //以下公共静态方法返回单例对象(如有必要就创建它)
public static SingletonDoubleCheck GetSingleton()
{
//如果单例对象已经创建,则直接返回它
if (s_value != null)
{
return s_value;
} //在指定对象上获取排他锁
Monitor.Enter(s_lock); //再次检查是否已经创建
//解决问题:若多个线程首次(单例对象还未创建)同时进入,此时,只有一个线程执行下面的代码(因为有Monitor),
//当该线程(第一个线程)创建完实例后,另一个线程(第二个线程)立即获得锁,也执行下面的代码,
//此时实例已经创建完成,后面的线程应该直接返回才对,因此再判断一次实例是否已经创建。
if (s_value == null)
{
//若仍未创建则创建它
SingletonDoubleCheck singleton = new SingletonDoubleCheck(); //将singleton给s_value
//下面的代码保证singleton中的引用只有在构造器结束执行之后才发布到s_value中
Volatile.Write(ref s_value, singleton); //注意:下面的写法是不牢靠的
//因为编译器可能会这样做:
//1.为SingletonDoubleCheck分配内存
//2.将引用发布到(赋给)s_value
//3.调用构造器
//假设在将引用发布给s_value之后,但在调用构造器之前,若有另一个线程调用了GetSingleton,
//此时s_value不为null,该线程会使用该对象,但该对象的构造器还没执行完成。
//s_value = new SingletonDoubleCheck();
} //释放指定对象上的排他锁
Monitor.Exit(s_lock); return s_value;
}
} /// <summary>
/// C#下简单的构造单例方法
/// CLR已保证了对类的构造是线程安全的,书写非常简便
/// 缺点也很明显,首次访问类的任何成员时都会调用类型构造器
/// 所以,如果该类定义了其它静态成员,就会在访问其它任何静态成员时创建该对象
/// </summary>
public sealed class SingletonSimple
{
private static SingletonSimple s_value = new SingletonSimple(); //私有构造器阻止这个类外部的任何代码创建实例
private SingletonSimple()
{ } //以下公共静态方法返回单例对象(如有必要就创建它)
public static SingletonSimple GetSingleton()
{
return s_value;
} //或
public static SingletonSimple SingletonInstance
{
get { return s_value; }
} //或
public static SingletonSimple Instance { get; } = new SingletonSimple();
} /// <summary>
/// 嵌套类实现单例
/// 如果多个线程同时调用GetSingleton,则可能创建多个SingletonNested对象
/// 但由于使用了Interlocked.CompareExchange,所以保证只会有一个引用被发布到s_value
/// 没有被固定下来的对象都会被垃圾回收
/// 该种方式不会阻塞线程
/// </summary>
public sealed class SingletonNested
{
private static SingletonNested s_value = null; //私有构造器阻止这个类外部的任何代码创建实例
private SingletonNested()
{ } //以下公共静态方法返回单例对象(如有必要就创建它)
public static SingletonNested GetSingleton()
{
//如果单例对象已经创建,则直接返回它
if (s_value != null)
{
return s_value;
} //创建一个新的单例对象,并把它固定下来(如果另一个线程还没有固定它的话)
SingletonNested singletonNested = new SingletonNested(); //比较两个指定的引用类型的实例 T 是否相等,如果相等,则替换第一个,并且返回s_value原始值
//s_value与null比较,如果相等则用singletonNested替换s_value,否则不替换
Interlocked.CompareExchange(ref s_value, singletonNested, null); //如果该线程竞争失败,则新建的第二个单实例对象会被垃圾回收 return s_value;
}
}
三种方式构建C#单例模式的更多相关文章
- 彻底了解构建 JSON 字符串的三种方式
原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7701856.html 前言:JSON 是轻量级的数据交换格式,很常用,尤其是在使用 Ajax ...
- python实现单例模式的三种方式及相关知识解释
python实现单例模式的三种方式及相关知识解释 模块模式 装饰器模式 父类重写new继承 单例模式作为最常用的设计模式,在面试中很可能遇到要求手写.从最近的学习python的经验而言,singlet ...
- Solon 开发,三、构建一个Bean的三种方式
Solon 开发 一.注入或手动获取配置 二.注入或手动获取Bean 三.构建一个Bean的三种方式 四.Bean 扫描的三种方式 五.切面与环绕拦截 六.提取Bean的函数进行定制开发 七.自定义注 ...
- C#批量插入数据到Sqlserver中的三种方式
本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生 成 ...
- PHP的学习--连接MySQL的三种方式
记录一下PHP连接MySQL的三种方式. 先mock一下数据,可以执行一下sql. /*创建数据库*/ CREATE DATABASE IF NOT EXISTS `test`; /*选择数据库*/ ...
- php 链接mysql的三种方式对比
PHP连接Mysql的三种方式: 1.原生的连接方式 原生的连接方式是面向过程的写法 <?php $host = 'localhost'; $database = 'test'; $usern ...
- dubbo服务运行的三种方式
dubbo服务运行,也就是让生产服务的进程一直启动.如果生产者进程挂掉,也就不存在生产者,消费者不能进行消费. Dubbo服务运行的三种方式如下:1.使用Servlet容器运行(Tomcat.Jett ...
- python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用django)
昨日内容回顾 1. 内容回顾 1. VueX VueX分三部分 1. state 2. mutations 3. actions 存放数据 修改数据的唯一方式 异步操作 修改state中数据的步骤: ...
- Spring MVC异常统一处理的三种方式
Spring 统一异常处理有 3 种方式,分别为: 使用 @ ExceptionHandler 注解 实现 HandlerExceptionResolver 接口 使用 @controlleradvi ...
随机推荐
- 敏捷管理的大概背景和Scrum的特性
我们在转型Scrum敏捷开发时,一直会有一个很大的困惑问题,那就是我的团队适不适合使用敏捷项目管理工具和开发方式.我大概总结了下Scrum的大概样子可以参考下.总之敏捷管理不是口号,他只是一种工具,只 ...
- OpenCV.资料(20190717)
1.opencv将图片转换为视频 - zeng_haoyu的博客 - CSDN博客.html(https://blog.csdn.net/hy13684802853/article/details/8 ...
- 一道RAID面试题
- 什么是 redis 的雪崩、穿透和击穿?
缓存雪崩 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机.缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据 ...
- 《C和指针》读书笔记
1. 三字母词 三字母词即用三个字符合起来表示另一个字符,它可以使C环境在某些缺少一些必需字符的字符集上实现. ??( [ ??< { ??= # ??) ] ??> } ??/ \ ?? ...
- fzu1704(高斯消元法解异或方程组+高精度输出)
题目链接:https://vjudge.net/problem/FZU-1704 题意:经典开关问题,求使得灯全0的方案数. 思路:题目保证至少存在一种方案,即方程组一定有解,那么套上高斯消元法的板子 ...
- 飞腾1500A 上面银河麒麟操作系统 进行远程以及添加用户的方法 linux xrdp
1. 安装远程用的软件: sudo apt-get install xrdp vnc4server xbase-clients systemctl enable xrdp systemctl star ...
- ajax提交 的编码小结
今天用ajax的post方法提交数据给webservice,由于有email的缘故发现,注册方法调用总是报错,打开报文一看提交的 发现@符号被变成了%40 , abc@126.com 即abc%401 ...
- C++ Primer练习题day2
/* 1.7略 1.8 /* 指出不合法的语句: std::cout<<"/"; std::cout<<"*/ "; std::cout ...
- selenium弹框元素定位-冻结界面
有些网站上面的元素,我们鼠标放在上面,会动态弹出一些内容. 比如,百度首页的右上角,有个更多产品选项,如下图所示: 如果我们把鼠标放在上边,就会弹出下面的百度营销.音乐.图片等图标. 如果我们要用se ...