• 关于线程安全的单例模式的讨论


    其实这个问题断断续续研究了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;

    最后带着不甘感谢我的同事剑周。

    ----循例的一段签名:山外有山,人外有人,吾当自强,诸君共勉

  • 相关阅读:
    MySQL热备脚本
    从库查看状态的时候显示“ Last_Error”
    Jenkins+svn+maven
    confluence的安装、备份和恢复(wiki)
    RAP在centos上的部署
    不停止MySQL服务的情况下修改root的密码
    给Linux装图形化界面
    大文件传输工具
    MySQL server PID file could not be found!
    find常见用法
  • 原文地址:https://www.cnblogs.com/gssl/p/3463473.html
Copyright © 2020-2023  润新知