设计模式研究:单例

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

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

一、非线程安全的单例:

 1     public class Singleton
2 {
3 private static Singleton instance;
4 private Singleton() { }
5
6 public static Singleton GetInstance
7 {
8 get
9 {
10 if(null == instance)
11 {
12 instance = new Singleton();
13 }
14 return instance;
15 }
16 }
17 }

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

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

 1     public class Singleton
2 {
3 private static Singleton instance = new Singleton();
4 private Singleton() { }
5
6 public static Singleton GetInstance
7 {
8 get { return instance; }
9 }
10 }

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

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

 1     public class Singleton
2 {
3 private static Singleton instance;
4 private Singleton() { }
5
6 [MethodImpl(MethodImplOptions.Synchronized)]
7 public static Singleton GetInstance()
8 {
9 if (null == instance)
10 {
11 instance = new Singleton();
12 }
13 return instance;
14 }
15 }

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

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

 1     public class Singleton
2 {
3 private static readonly object syncObj = new object();
4 private static Singleton instance;
5 private Singleton() { }
6
7 public static Singleton GetInstance
8 {
9 get
10 {
11 if (null == instance)
12 {
13 lock (syncObj)
14 {
15 if (null == instance)
16 {
17 instance = new Singleton();
18 }
19 }
20 }
21 return instance;
22 }
23 }
24 }

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

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

 1     public class Singleton
2 {
3 private static Singleton instance;
4 private Singleton() { }
5
6 public static Singleton GetInstance
7 {
8 get
9 {
10 if (null == instance)
11 {
12 System.Threading.Interlocked.CompareExchange(ref instance, new Singleton(), null);
13 }
14 return instance;
15 }
16 }
17 }

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

六、使用单例模式的注意事项:
1:如果系统内存在多种类型的单例,那么这些单例之间不应该存在依赖关系 。如果确实存在非依赖不可的单例,证明你在设计上将不应该单例的对象单例了。或者是把你的设计把本应该一个单例的拆分为了多个单例。
2:一个类是否应该使用单例模式,不应该由类自己决定,而应该由类的使用者来决定。

 

转载于:https://www.cnblogs.com/mitnickzhou/archive/2011/11/06/2238084.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值