2011-04-27 79 views
2

看看下面的代碼:線程安全類和方法參數

public void SomeMethodWithParameters(MutableObject mutableParameter, String stringParameter, double structParameter) 
    { 
     // some code 
    } 

這是我的理解,這個代碼是不是線程安全的,由於這樣的事實,mutableParameter是這種方法的多變之外。

你在代碼中使用什麼策略(除了只使用不可變的類或結構作爲參數)以防止這種可能性?是否所有傳遞的對象都是這個方法實際上是深層克隆?

+0

在C#中,我認爲「參考參數」的通常含義是'ref'參數。也許「參考類型的參數」會更清楚? – recursive 2011-04-27 21:20:31

+0

這只是一個問題*如果* mutableParameter *可以*在方法調用期間更改。如果沒有其他線程具有對mutableParameter的引用,那麼在方法外部更改它並不重要,因爲它不會更改... – forsvarir 2011-04-27 21:21:36

+0

爲了論證的緣故,它*在方法調用之外是可修改的。 – miguel 2011-04-27 21:27:57

回答

9

這是我的理解,這個代碼是不是線程安全的,因爲mutableParameter在此方法之外是可以改變的。

澄清:的內容的可變「mutableParameter」是不會改變的;該變量將在其整個生命週期中引用相同的實例(前提是您不要在方法中更改它)。被引用的實例所擁有的變量的內容可能會改變,如果其他有相同對象的引用的其他線程正在改變它們。

你在代碼中使用什麼策略(除了只使用不可變類或結構作爲參數)以防止這種可能性?

如果可能,請完全避免此問題。不要首先在多個線程上讀取和寫入同一對象的相同變量。

如果你無法避免它,那麼創建一個適當可訪問的鎖定對象。

定義一個鎖定協議,以便您承諾在訪問任何可以在另一個線程上訪問的變量之前鎖定該對象。完成後解鎖。

  • 請確保訂購您的鎖以防止死鎖。
  • 鎖定對象應儘可能無法訪問。私人比內部更好,內部更好,比公共更好。切勿選擇類型作爲鎖對象;你無法控制誰按照什麼順序鎖定它,因此你有可能陷入僵局。
  • 確保訪問變量線程遵循協議。無論如何鎖定100個通道中的99個並且沒有鎖定地將第100個鎖定在任何位置都沒有用。如果你不能防止你不能控制訪問資源的代碼,那麼資源本身需要重寫成線程安全。
  • 衡量你的表現,看看鎖的競爭頻率。如果鎖被嚴重爭奪,請更改您的架構以防止爭用。只有當你絕對肯定地有一個嚴重的問題,如果你嘗試一種無鎖或低鎖解決方案,你無法以其他方式改善。
+0

瞭解內容與參考本身。 – miguel 2011-04-27 21:21:22

+0

但是如果您傳遞給方法的類參數也可以從另一個類中修改,那麼如何確保您鎖定在同一個對象實例上(無靜態) – miguel 2011-04-27 21:27:16

+1

@miguel:現在您知道爲什麼寫這麼難正確的多線程代碼!你必須設計一個適用於你所面對的具體情況的協議。你如何做到這一點取決於你。 – 2011-04-27 21:29:00