【单例模式】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 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式.这种模式涉及到一个单一的类,该类负责创建自己的对象 ...
随机推荐
- [三卷天书]ajax请求时接收到乱码的处理方案
$.ajax({ url: "getmore.ashx", type: "post", dataType: "text", data: { ...
- 蓝桥杯 算法训练 ALGO-15 旅行家的预算
算法训练 旅行家的预算 时间限制:1.0s 内存限制:256.0MB 问题描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离D1.汽车 ...
- java中求利息的代码
总结:函数的重要性,懂得用哪一种函数 package com.badu; import java.util.Scanner; //输入存款金额 money.存期 year 和年利率 rate, //根 ...
- netty中的UDP
UDP 提供了向多个接收者发送消息的额外传输模式: 多播——传输到一个预定义的主机组: 广播——传输到网络(或者子网)上的所有主机. 本示例应用程序将通过发送能够被同一个网络中的所有主机所接收的消息来 ...
- PL/SQL 训练03 --异常
--程序员在开发的时候,经常天真的认为这个世界是完美的,用户如同自己般聪明,总能按照自己设想的方式--操作系统输入数据.但残酷的事实告诉我们,这是不可能的事情,用户总会跟我们相反的方式操作系统--于是 ...
- python开发模块基础:re正则
一,re模块的用法 #findall #直接返回一个列表 #正常的正则表达式 #但是只会把分组里的显示出来#search #返回一个对象 .group()#match #返回一个对象 .group() ...
- CORS跨域资源共享漏洞
CORS漏洞其中已经存在很久了,但是国内了解的人不是很多,文章更是少只有少,漏洞平台也没有此分类. 在DefConChina之后写了一篇算是小科普的文章. 定义CORS,Cross-Origin Re ...
- Zookeeper 基础、工作流、ZAP协议
ZooKeeper 基础 在深入了解ZooKeeper的运作之前,让我们来看看ZooKeeper的基本概念.[1] 我们将在本章中讨论以下主题:1.Architecture(架构)2.Hierarch ...
- Java中long和Long的区别
Java的数据类型分两种: 1.基本类型:long,int,byte,float,double,char,short,boolean 2. 对象类型(类): Long,Integer,Byte,Flo ...
- vs2008评估期已过的解决方法[win7]
以下是网上提供的方法(对win7无效): 启动visual studio 2008后显示对话框:visual studio的试用版评估期已结束.下面有两个按钮,点第一个链接到微软网页,第二个直接关闭. ...