【单例模式】Singleton pattern
前言:有很多时候,在一个生命周期中我们只要一个对象就可以了,比如:线程池,缓存,对话框,日志,显卡驱动等等。如果造出多个实例,就会导致许多问题产生,例如:程序的行为异常、资源使用过量,或者说不一致的结果。
public class Singleton
{
private static Singleton instance;
private Object _synchronizedObj = new Object(); //private constructor
private Singleton() { } public Singleton GetInstance
{
get
{
if (instance == null)
lock (_synchronizedObj)
{
if (instance == null)
instance = new Singleton();
}
return instance;
}
}
}
这里用到了Lock, 我看过大部分代理都没有使用到这里,但是如果不用上,在有多线程的项目中就会出现问题。
我用了两次NULL的判断,最外层说因为如果你第一次创建好了就不需要去进行LOCK,这里会有消耗。里面那一个NULL判断是因为如果你有多个线程一起来创建,都通过第一层NULL限制,进入了LOCK等待,当第一个对象创建完,放开了LOCK,第二进去以后,如果不加判断又会创建一次。
有人和我说这样会不会更优雅,因为不用一个成员变量Object.
public class Singleton
{
private static Singleton instance; //private constructor
private Singleton() { } public Singleton GetInstance
{
get
{
if (instance == null)
lock (typeof(Singleton)) //here
{
if (instance == null)
instance = new Singleton();
}
return instance;
}
}
}
这里不得不提及 同步索引块(Sync block index),这个东西被关注的特别少,既然说学习CLR,这个东西可是叱咤风云(不过大部分的时候,你不会用而已啦).
Sync block index 初始化和过程
当CLR初始化的时候,CLR会初始化一个SyncBlock的数组,当一个线程到达Monitor.Enter方法时,该线程会检查该方法接受的参数的同步块索引,默认情况下对象的同步块索引是一 个负数
(实际上并不是负数,我这里只是为了叙说方便),那么表明该对象并没有一个关联的同步块,CLR就会在全局的SyncBlock数组里找到一个空闲的项,然后将数组的索引赋值给该对象的同步块索
引,当Monitor.Enter执行时,它会设置SyncBlock里的内容,标识出已经有一个线程占用了,当另外一个线 程进入时,它就会检查SyncBlock的内容,发现已经有一个线程占用了,该线程就
会等待,当Monitor.Exit执行时,占用的线程就会释放SyncBlock,其他的线程可以进入操作了。 注:参考博客园另一篇文章:http://www.cnblogs.com/qianyz/archive/2011/10/26/2224925.html(若要了解更多的SyncBlockIndex的用途和原理,可以看这篇)
所以对于上面的代码:
typeof(Singleton)返回一个Type对象,如果用这个,会返回相同TYPE对象。我们在这里用lock(typeof(Singleton))锁定了,相当于锁定返回的TYPE对象。OK,当我们在其他在用lock(typeof(Singleton))的时候,又锁了这个对象...2个地方锁了用了同一个对象,结果不该等待的地方也在等待了。 所以我们这里用了私有的Object对象来充当关联进索引块的对象,无论外面这么锁,都锁不住者里东西。
最近逛博客的时候发现一篇文章说完美单例的,我不是很清楚完美不完美,不过的确要比我认知的单例性能要好写,附上代码:
public class Singleton
{
private Singleton()
{
} private static class SingletonFactory
{
public static readonly Singleton Instance; static SingletonFactory()
{
Instance = new Singleton();
}
} public static Singleton GetInstance()
{
return SingletonFactory.Instance;
}
}
那边文章说的说Java的单例,谈到了JVM的加载机制(JVM保证了类加载的时候是互斥的)如果CLR呢?静态类在加载包含该类的程序或命名空间时由 .NET Framework 公共语言运行库 (CLR;特指:C#语言) 自动加载,由于静态类里面不能有实例构造(这个很靠谱),我们造了一个静态构造(相对于java的static{})来初始化对象,因为在类加载的时候就会初始化这个对象(类加载是互斥的),所以我们就不用锁对象了,直接调用就可以。
好处:这个相当于以前的版本,减少了判断和锁的机制,而且这里为什么会用静态类来做初始化工作,首先这个单例的类可能被继承,方法可能被重写,还有可能要继承一些接口,所以用内部静态类来做的话(静态类不能实现接口,不能被继承)功能非常的单利,就算Singlton被继承了,方法被重写,无论什么机制,我们初始化单例的地方已经得到控制,外部是不能随心所欲的去改变创建单例的模式,只能做一些自己要的修饰,然后再调用内部静态类获取单例子,这也可以说是一层封装。
我和同事讨论一下这个模式,它固有自己的好处,但是缺点也很明显,我构建一个Connection对象的时候,我Disponse了,这样的话我们并不能在获得一次对象(如果获取对象
的时候出错了,也无法再获取一次,要写主动加载,这样并没有封装好),但是这个东西如果要构建大对象的话,封装的还是不错,还要考虑一下大对象的资源问题(因为是
static的,GC可不管你), 我一直认为,写模式,要写成我不知道这个是什么模式,但是用在我这个场景是最合适的,这样模式就贯通了,而不是生搬硬套...
【单例模式】Singleton pattern的更多相关文章
- 浅谈设计模式--单例模式(Singleton Pattern)
题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...
- 设计模式之单例模式(Singleton Pattern)
单例模式 单例模式(Singleton Pattern)在java中算是最常用的设计模式之一,主要用于控制控制类实例的数量,防止外部实例化或者修改.单例模式在某些场景下可以提高系统运行效率.实现中的主 ...
- 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)
原文:乐在其中设计模式(C#) - 单例模式(Singleton Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 单例模式(Singleton Pattern) 作者:weba ...
- 【设计模式】单例模式 Singleton Pattern
通常我们在写程序的时候会碰到一个类只允许在整个系统中只存在一个实例(Instance) 的情况, 比如说我们想做一计数器,统计某些接口调用的次数,通常我们的数据库连接也是只期望有一个实例.Windo ...
- 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)
在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...
- 二十四种设计模式:单例模式(Singleton Pattern)
单例模式(Singleton Pattern) 介绍保证一个类仅有一个实例,并提供一个访问它的全局访问点. 示例保证一个类仅有一个实例. Singleton using System; using S ...
- 设计模式系列之单例模式(Singleton Pattern)——确保对象的唯一性
模式概述 模式定义 模式结构图 饿汉式单例与懒汉式单例 饿汉式单例 懒汉式单例 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 主要优点 适用场景 说明:设计模式系列文章是读刘伟所著 ...
- Net设计模式实例之单例模式( Singleton Pattern)
一.单例模式简介(Brief Introduction) 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯 ...
- 深入设计模式(二)——单例模式(Singleton Pattern)
一.单例模式介绍 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯一实例,它就可以严格地控制客户怎样访问它 ...
- 设计模式系列之单例模式(Singleton Pattern)
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式.这种模式涉及到一个单一的类,该类负责创建自己的对象 ...
随机推荐
- 如何让公司从SVN改到Git?
把公司的SVN迁移到GitLab CE(GitLab社区版)原因主要有下面几个: 年青的新人进来,喜欢用git的越来越多 GitLab CE提供了优美的 web 界面,图形化分支结构,更直观的代码审查 ...
- (转)Oracle执行字符串
declare v_out ); begin execute immediate 'select p_guid from c_itcomp where rownum = 1 ' into v_out; ...
- 让memcached分布式
memcached是应用最广的开源cache产品,它本身不提供分布式的解决方案,我猜想一方面它想尽量保持产品简单高效,另一方面cache的key-value的特性使得让memcached分布式起来比较 ...
- 城市间紧急救援(25 分)(dijstra变形)
城市间紧急救援(25 分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标 ...
- PHP定时任务Crontab结合CLI模式详解
从版本 4.3.0 开始,PHP 提供了一种新类型的 CLI SAPI(Server Application Programming Interface,服务端应用编程端口)支持,名为 CLI,意为 ...
- mac常用命令(随时更新)
mac 强制退出快捷键 1.使用键盘快捷键强制退出处于活跃状态的Mac程序 快捷键:Command+Option+Shift+Esc 这样按住一两秒钟,就可以强制退出当前程序了,算是最方便的一种方法. ...
- C#多线程List的非线程安全性
背景:最近在做多线程方面的工作,工作中发现多线程中很多坑,这里就有一个List添加对象的误区,这里做个分享跟大家讲讲这个坑是怎么形成的怎么样避免. 示例: 代码及错误: 如果单单只从程序逻辑上看,应该 ...
- Java学习之Dubbo+ZooKeeper分布式服务Demo
背景:在之前的一个<Java学习之SpringBoot整合SSM Demo>分享中说到搭建ZooKeeper和Dubbo分布式框架中遇到了一些技术问题没能成功,只分享了其中的一个中间产物, ...
- HttpURLConnection连接网页和获取数据的使用实例
HttpURLConnection是java.net 里面自带的一个类,非常好用.虽然现在很多人用阿帕奇的HttpClient,但HttpURLConnection也是个不错的选择. 其实使用方法非常 ...
- Elasticsearch之kopf插件安装之后的浏览详解
前提, Elasticsearch之插件介绍及安装 https://i.cnblogs.com/posts?categoryid=950999&page=2 (强烈建议,从头开始看) 比如, ...