最近在 Review 代码的时候,发现大量类似如下风格的单件(Singleton)类:     /** <summary>

/// 线程不安全的 Singleton
     /// </summary>
     public class Singleton
     {
         static private Singleton instance;
         
         private Singleton()
         {
             //
             // TODO: Add constructor logic here
             //
         }        static Singleton Instance
         {
             get
             {
                 if( instance == null )
                     instance = new Singleton();
                 return instance;
             }
         }
     }


    乍一看还很经典,但细一推敲,却发现了问题:
    
    当多个线程同时调用 Singleton.Instance 属性的时候,每个线程都检测到 instance == null 为真,于是每个都会傻乎乎的创建一个新实例.这将导致最先创建的实例实效,只有最后创建的实例被保存在静态的 instance 中.虽然这在大多数情况下不会引发大问题,但一旦构造函数中有比较耗时的操作,则会造成程序逻辑上的错误.而这些通常都是隐藏得很深,而且很难复现的超级大Bug .所以,要小心哪,同志们!

    为了避免这种问题,我采用了下面的代码:

/** <summary>
     /// 线程安全的 Singleton
     /// </summary>
     public class ThreadSafeSingleton
     {
         static private ThreadSafeSingleton instance;
         static private object syncObj = new object(); //用于线程同步        private ThreadSafeSingleton()
         {
             //
             // TODO: Add constructor logic here
             //
         }        static ThreadSafeSingleton Instance
         {
             get
             {
                 lock( syncObj )  //使用 Monitor 同步
                 {
                     if( instance == null )
                         instance = new ThreadSafeSingleton();
                     return instance;
                 }
             }
         }
     }

posted on 2006-02-17 00:06 录一事流 阅读(80) 评论(4)  编辑 收藏 收藏至365Key 所属分类: 多线程编程技术 
 
Feedback 

# re: 编写线程安全的单件(Singleton)
 2006-02-17 00:47 | lx 
 static ThreadSafeSingleton Instance 
 { 
 get 
 { 
 if( instance == null ) 
 { 
 lock( syncObj ) //使用 Monitor 同步 
 { 
 if( instance == null ) 
 instance = new ThreadSafeSingleton(); 
 } 
 } 
 return instance; 
 } 
 }


  回复
   
# re: 编写线程安全的单件(Singleton)
2006-02-17 08:01 | 补丁 
又写一遍: 

public class ThreadSafeSingleton 
 { 
 private ThreadSafeSingleton() 
 { 
 } public static ThreadSafeSingleton Instance = getInstance(); 
static ThreadSafeSingleton getInstance() 
 { 
 return new ThreadSafeSingleton(); 
 }