2012-11-07 51 views
4

如果我有一個ConcurrentDictionary並在if語句中使用TryGetValue,這是否會使if語句的內容線程安全?還是必須鎖定在if語句中?在if語句中使用ConcurrentDictionary TryGetValue是否使if內容線程安全?

例子:

 ConcurrentDictionary<Guid, Client> m_Clients; 

     Client client; 
     //Does this if make the contents within it thread-safe? 
     if (m_Clients.TryGetValue(clientGUID, out client)) 
     { 
      //Users is a list. 
      client.Users.Add(item); 
     } 

或做我必須做的:

 ConcurrentDictionary<Guid, Client> m_Clients; 

     Client client; 
     //Does this if make the contents within it thread-safe? 
     if (m_Clients.TryGetValue(clientGUID, out client)) 
     { 
      lock (client) 
      { 
       //Users is a list. 
       client.Users.Add(item); 
      } 
     } 
+0

'TryGetValue'本身是線程安全的...它不會使'if語句線程安全......在示例中,您的節目需要'鎖定'。 – Yahia

+0

感謝您解決這個問題。我見過一堆使用像這樣的對象進行鎖定的示例:private readonly object m_lock = new object(); 。我可以鎖定我的方式,還是應該使用對象進行鎖定? – Mausimo

+0

這取決於你想實現的目標 - 如果你想確保客戶端的實例只能被一個線程修改,那麼就使用你當前的方法......另一種方法可以被實現,甚至可以在全局序列化變化,例如... – Yahia

回答

4

是的,你必須if語句裏面鎖住你的併發字典唯一能把握的是,它的方法是線程保存。

+0

謝謝,還有一個後續問題:我已經看到了一堆使用像這樣的對象進行鎖定的示例:private readonly object m_lock = new object(); 。我可以鎖定我的方式,還是應該使用對象進行鎖定? – Mausimo

+0

推薦的方法是用新對象鎖定。請參閱[this](http://msdn.microsoft.com/zh-cn/library/c5kehkcz%28v=vs.110%29.aspx)。 – Rafal

+0

再次感謝。理解:如果我使用只讀對象方法進行鎖定。然後我在同一個對象中鎖定2種不同的方法,並且在不同線程的同一個實例上調用這兩種方法。那麼,這兩種方法會有爭用嗎?我應該使用2個只讀鎖對象,每個方法1個? – Mausimo

0

根據您的觀點以及您嘗試實現的線程安全範圍,接受的答案可能會產生誤導。這個答案的目的是誰在這個問題上絆倒,同時瞭解線程和併發人:

這是真的,鎖定詞典中檢索(客戶對象)的輸出產生代碼線程安全的一些,但只有正在訪問鎖中檢索到的對象的代碼。在該示例中,可能會有另一個線程刪除該對象來自之後的對象當前線程檢索到該對象。 (即使檢索和鎖之間沒有語句,其他線程仍可以在兩者之間執行)。然後,此代碼將Client對象添加到Users列表中,即使它不在併發字典中。這可能會導致異常,同步或爭用情況。

這取決於程序的其餘部分在做什麼。但是在我描述的場景中,將鎖放在整個字典檢索中會更安全。然後,一個普通的字典可能比並發字典更快,更簡單,只要你在使用它的時候總是鎖定它!