2014-01-11 35 views
1

在C#中,類實例是引用類型。這是否意味着可以鎖定由new返回的值的副本?在我的情況下,我有一些需要鎖定的字段:我可以鎖定類實例變量的副本嗎?

class Foo { 
    // ... 
    private Dictionary<IAsyncResult, string> fReadRequests; 
    private Dictionary<IAsyncResult, string> fWriteRequests; 
    private Dictionary<IAsyncResult, string> fSyncRequests; 
} 

在一個特定的方法中,我需要對所有這些字段執行相同的操作。因此,爲了避免代碼重複,我通過將字段複製到數組中來執行循環操作:

var dictArray = new[] { fReadRequests, fWriteRequests, fSyncRequests }; 
foreach (var reqDict in dictArray) { 
    lock (reqDict) { 
     foreach (var i in reqDict) { 
      // Do something with the request. 
     } 
    } 
} 

這是安全嗎?即使鎖上應用的變量是原件的副本,鎖定是否按預期工作?

+0

不知道這是不是你的意思,但存儲在'reqDict' *中的'Dictionary'不會是字典的副本,它將是對原始字典的引用,所以它將工作就像你複製每個字典的代碼一樣。 –

+0

總之,是的,你的鎖定應該可以正常工作! – Baldrick

+0

@ T.凱利 - 所以參考(不是實例)是一個副本。 –

回答

5

是的,你永遠不會鎖定變量持有參考,你總是鎖定實例

你的情況,你複製參考,而不是對象,所以這就是你對工作的同一對象是在這些領域。

鎖定這些應該很好。

只知道:

  1. 鎖定的對象不以任何方式阻止其他線程訪問同一個對象。如果另一個線程未鎖定,它將跳入正確的位置,並改變對象而不理會您的鎖定。
  2. 請勿鎖定您不擁有的對象以及您發佈給他人的對象。您需要確保您的代碼是鎖定該對象的唯一一個,否則如果某些其他代碼也對其鎖定,那麼您的小心同步代碼可能會突然停止。
  3. 從不鎖定值類型,即使您將它們放在object變量中。每次將值類型複製到object變量中時,您將獲得新的副本,該副本將擁有自己的鎖定。

爲了對抗nbr。 2你通常這樣做:

private readonly object fLockReadQuests = new object(); 

然後鎖定,而不是。

但是,您的問題的假設仍然存在。

+0

謝謝。對於我在這裏找到的比我在C#中擁有更長的經驗的人來說,這是非常讓人放心的,而且您已經提供了這一點。 –

相關問題