淺談c#中使用lock的是與非(轉)

iDotNetSpace發表於2010-09-19
1、從“最簡單”的單例模式說起:
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gtpublic class Singleton
{
    
private static Singleton instance = null;
    
private static readonly object syncRoot = new object();

    
private Singleton()
    {
    }

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

  稍微瞭解設計模式基礎知識的人對上面的程式碼應該不會陌生。上次去面試,主考官就讓樓豬寫個單例。雖然平時已經很久沒有刻意去使用設計模式程式設計了,但是對於這個單例模式,咩哈哈,雖然大丈夫喜怒不形於色,但是nc樓豬當時那個意氣風發躊躇滿志運筆如飛鋒芒畢露啊,嘿嘿,中規中矩地交了如上答案。面試官看了一下肯定了兩句,話鋒一轉,問lock那裡的object例項可以直接用instance替代嗎?new一個object是否多餘,可否寫成下面的形式:

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --&gtpublic class Singleton
{
    
private static Singleton instance = null;
    
//private static readonly object syncRoot = new object();

    
private Singleton()
    {
    }

    
public static Singleton GetInstance()
    {
        
if (instance == null)
        {
            
lock (instance)//instance能替換syncRoot嗎?
            {
                
if (instance == null)
                {
                    instance 
= new Singleton();
                }
            }
        }
        
return instance;
    }
}

  雖然在這個問題前面,面試官問的一個資料庫設計和幾個c#的小問題(有一個題樓豬當時竟然嘴硬說那是“奇技淫巧”,好怕怕)很見知識深度和修養,樓豬已經小有提防,但是這個問題還是再次讓樓豬自亂陣腳。以前從來沒人問過樓豬這個問題,樓豬也沒主動想過它,腦袋裡一片白茫茫,剛想要鎮定下來,面試官又把相同問題問了一遍。不及細想,雖然不能確定,但是還是回答“應該可以...吧”(語氣助詞用得妙啊)。
  肯定是對這個回答和回答的語氣不滿意,面試官又提醒問lock機制是什麼樣的,說說c#大概是怎麼實現lock的。樓豬語無倫次說lock本質上和作業系統相關,lock就是當前執行緒將資源獨佔其他執行緒不能訪問該鎖定資源云云,背書都不會背了嗎?無語了。面試官說回去自己試試吧。聽他的語氣,答案當然不言自明瞭,小心靈遭受重大挫折和打擊啊。
  回來後,驗證了一下面試官的問題,程式執行到lock的時候,丟擲ArgumentNullException異常,“值不能為null”。為什麼lock一個指向null的引用例項不可以呢?
      查了一下中文msdn

lock 確保當一個執行緒位於程式碼的臨界區時,另一個執行緒不進入臨界區。如果其他執行緒試圖進入鎖定的程式碼,則它將一直等待(即被阻止),直到該物件被釋放。


     老實說,直到看到最後一句“物件被釋放”才給了樓豬提示。某一物件可以指向null引用,但是null關鍵字是不需要釋放的吧?!是嗎?查了一下高人anytao的部落格,發現這篇認識全面的null給出了明確的答案。
      接著樓豬又檢視了一下經常可以替代lock的Monitor類,赫然發現它的靜態方法Enter(object obj)有一個異常型別ArgumentNullException,早知道,也不會那麼狼狽啊。

2、lock的陷阱
除了msdn裡提到的lock需要注意的兩點外,園子裡早就有高手總結過了,可以參考這一篇

3、最後自己總結得出的三個結論:
a、c#中null是不能lock的(null會分配記憶體嗎,會佔用系統資源嗎?和樓豬一起思考和探討吧)。
b、高手一出手,往往可以化腐朽為神奇。
c、對自己說:
加油。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-674405/,如需轉載,請註明出處,否則將追究法律責任。

相關文章