其实这个问题断断续续研究了1个多星期了 主要是想开一条线程来监听用户登录的状态 好吧 还是打点标点符号好了。
说这个事情之前不得不说的一些背景。首先呢,我是写过多线程的,但是失败了。那是3年前读大学的时候,自己想着不按老师提出的课题,硬是要写一个简单的动作游戏。然后,老师说不能用IDE环境,只能用TXT,然后只有两个星期时间,那个是JAVA的,编译的时候还得用cmd来玩~~然后我写出来的程序非常诡异~ 然后只有60多分吧。然后我发现大家貌似都用MyEclipse或者Netbeans来写,好像。。我只能说那个老师鼓励学生的方式有点奇怪。。客观来说,那个游戏是失败的,我的努力和产出的结果让我针对自己的智商进行了重新评估~那时候两个星期基本很多时候都是在看JAVA的多线程,那个。。。看不懂~~然后埋下了深深的自卑和挫折感。。。
然后最近做项目里用户管理这块,由于这个项目是2年前的我来构建的。那可是杠杠的本B学校实验项目水平~ 用户这块也是用Session来判定的~比较简单~ 然后想着趁这个机会重构一下我的项目~主要是针对后台架构这块做出一些调整。然后觉得后台这块必须要用到多线程技术~ 因为分布式的应用或者现在开始火起来的BigPip都用到了多线程技术。然后遇到了需要用单例的情况,然后遇到了单例+多线程。。然后一切就这么发生了~~很自然的 直接遇到了多线程实例化单例类。。。
既然说到单例,不得不说单例的几种模式:
第一种,类定义的时候就加载了~:
public final class EagerSingleton { private static EagerSingleton singObj = new EagerSingleton(); private EagerSingleton(){} public static EagerSingleton getSingleInstance(){ return singObj; } }
第二种是延迟加载:
public final class LazySingleton { private static LazySingleton singObj = null; private LazySingleton(){ } public static LazySingleton getSingleInstance(){ if(null == singObj ) singObj = new LazySingleton(); return singObj; } }
然后是延迟加载的亚种,也是这次故事的主角--双重检查锁(Double-Checked Lock)
public final class DoubleCheckedSingleton { private static DoubleCheckedSingletonsingObj = null; private DoubleCheckedSingleton(){ } public static DoubleCheckedSingleton getSingleInstance(){ if(null == singObj ) { Synchronized(DoubleCheckedSingleton.class){ if(null == singObj) singObj = new DoubleCheckedSingleton(); } } return singObj; } }
文章里面提出了双重检查锁会有一个情况是返回不完全对象,因此这种锁机制是不安全的。然后产生了一下的产物:(JAVA的)
public class Singleton { private static class SingletonHolder { public final static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
这里用到了JAVA的优势~,但是我的是C#的项目~。故事继续:
然后,我找到了一个小伙子(刚毕业半年吧)跟他一起商量~ 我跟他说明了情况(主要介绍了双重锁这些东西),他说要不给一个中间变量,让他实例完了再把这个中间变量赋值给返回的变量。然后参照双重锁的代码:
public class DoubleCheckedSingleton { private static DoubleCheckedSingletonsingObj = null; private DoubleCheckedSingleton(){ } public static DoubleCheckedSingleton getSingleInstance(){ if(null == singObj ) { Synchronized(DoubleCheckedSingleton.class){ if(null == singObj) DoubleCheckedSingleton buffer = new DoubleCheckedSingleton() singObj = buffer; } } return singObj; } }
这样在实例化的时候singObj的值始终为null,因此避免了返回不完全对象的可能性了。
然后我查了一些C#引用类型赋值的资料,觉得这个办法是可行的,后生可畏啊,有点失落,吾等互勉吧~
饮水思源,代码部分参考这里:
线程安全的单例模式 http://blog.sina.com.cn/s/blog_75247c770100yxpb.html;
最后带着不甘感谢我的同事剑周。
----循例的一段签名:山外有山,人外有人,吾当自强,诸君共勉