您的位置:首页 > 其它

设计模式研究:单例

2011-11-06 15:25 197 查看
  最近面试了很多兄弟,工作经验一般在2-3年,几乎所有的人都能对单例进行一般的解释,但是真正让他们手写一段单例代码的时候,能写得清楚明白的人就没几个了。下面我们一起来总结一下怎么写出一个好的单例。[源代码从这里下载]


目录
一、非线程安全的单例
二、未采用延迟加载的单例
三、采用线程同步方法实现的单例
四、采用双重锁实现的单例
五、【结论】采用原子操作实现的单例
六、使用单例模式的注意事项


一、非线程安全的单例:

public class Singleton
{
private static Singleton instance;
private Singleton() { }

public static Singleton GetInstance
{
get
{
if(null == instance)
{
instance = new Singleton();
}
return instance;
}
}
}


这种写法存在的问题是,当并发调用GetInstance属性的时候,由于多个线程同时进入了if判断,从而造成返回多个Singleton对象的隐患。这自然就有违我们的单例模式了。

二、未采用延迟加载的单例:

public class Singleton
{
private static Singleton instance = new Singleton();
private Singleton() { }

public static Singleton GetInstance
{
get { return instance; }
}
}


由于采用框架特性,这种写法确实是线程安全的,但是类型一旦加载,单例对象就已经存在,造成多余开销,如果构造函数耗时比较长的话,影响就更为突出了。

三、采用线程同步方法实现的单例:

public class Singleton
{
private static Singleton instance;
private Singleton() { }

[MethodImpl(MethodImplOptions.Synchronized)]
public static Singleton GetInstance()
{
if (null == instance)
{
instance = new Singleton();
}
return instance;
}
}


线程安全了,也延迟加载了,但是新的问题又来了,由于GetInstance方法在任何时候都只允许一个线程进入,带来的性能损失是不可忽视的。

四、采用双重锁实现的单例:

public class Singleton
{
private static readonly object syncObj = new object();
private static Singleton instance;
private Singleton() { }

public static Singleton GetInstance
{
get
{
if (null == instance)
{
lock (syncObj)
{
if (null == instance)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}


这样实现总该完美了吧,线程安全、延迟加载、效率都没有问题。但是如此写法稍显臃肿,就仅仅为了实现一个单例,搞了这么大一串括号,还为此引入了一个syncObj对象,还有更好的实现方式吗?

五、【结论】采用原子操作实现的单例:

public class Singleton
{
private static Singleton instance;
private Singleton() { }

public static Singleton GetInstance
{
get
{
if (null == instance)
{
System.Threading.Interlocked.CompareExchange(ref instance, new Singleton(), null);
}
return instance;
}
}
}


这种写法可以解决以上提到的所有问题,唯一需要提醒一点的是,在调用原子操作之前的判断语句是必不可少的,因为一旦执行CompareExchange方法必然会调用Singleton类型的构造函数,虽然不会引发多个instance对象的问题,但是会造成性能损失,如果构造函数耗时过长,影响将更为严重,所以在调用原子操作之前,先进性单例的判断,就能解决以上问题。

六、使用单例模式的注意事项:
1:如果系统内存在多种类型的单例,那么这些单例之间不应该存在依赖关系 。如果确实存在非依赖不可的单例,证明你在设计上将不应该单例的对象单例了。或者是把你的设计把本应该一个单例的拆分为了多个单例。
2:一个类是否应该使用单例模式,不应该由类自己决定,而应该由类的使用者来决定。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: