2014-09-01 80 views
3

我在.NET框架文檔的大多數地方已經注意到了以下聲明。爲什麼.Net框架類中的靜態方法總是線程安全的?

問題:什麼祕密呢?我不認爲靜態類總是線程安全的。我的問題涉及到.Net框架中提供的標準類,而不是開發人員創建的自定義類。

Thread Safety Note in all .Net Framework Classes documentation

會在靜態類中的方法「的GetString」下面是線程安全的,只是因爲該方法是一個靜態方法?

public static class MyClass 
{ 
    static int x = 0; 

    static MyClass() 
    { 
     x = 23; 
    } 

    public static string GetString() 
    { 
     x++; 
     return x.ToString(); 
    } 
} 
+1

它們不是線程安全的。 – kenny 2014-09-01 16:13:22

+2

默認情況下,代碼不是線程安全的 - 靜態或其他方式,聲明指出這些成員的設計考慮了線程安全性。 – Kami 2014-09-01 16:14:54

+0

那麼爲什麼說明靜態方法是線程安全的線程安全說明總是出現在我在.Net文檔中看到的所有.Net框架類中。我不是指開發人員創建的自定義類,而是框架附帶的類。 – Sunil 2014-09-01 16:15:27

回答

9

你提到的框架方法不是線程安全的距離其實他們是靜態的,而是因爲他們已經專門設計是線程安全的。線程安全性通常很難實現,但它通常對於靜態方法是必需的,因爲它們變異的任何狀態都是在線程之間共享的。

您發佈的抽樣方法是不是線程安全的,因爲它發生變異是線程之間共享的狀態,沒有任何同步機制。

+0

你知道他們爲什麼使所有的靜態方法都是線程安全的嗎?它不可能是一些隨機的巧合,但似乎有一些背後的模式/原因。 – Sunil 2014-09-01 16:18:12

+0

@Sunil,我剛剛編輯了我的回答,提到這一點。 – 2014-09-01 16:18:32

+0

好的。我現在明白了。謝謝。 – Sunil 2014-09-01 16:19:05

1

您提到的具體示例被設計爲線程安全的。這是他們允許併發訪問沒有死鎖或競賽條件。

這可能不是在所有類的所有實例的情況下,因此微軟選擇了明確說明哪些方法是線程安全的,哪些是不能避免任何含糊。

見最後一段 - 多線程環境中的.NET框架支持的併發訪問內.NET Class Library

所有公共靜態成員(方法,屬性,字段和事件)。因此,可以從兩個線程同時調用任何.NET Framework靜態成員,而不會遇到競爭條件,死鎖或崩潰。

對於.NET Framework中的所有類和結構,檢查API參考文檔中的線程安全部分,以確定它是否是線程安全的。如果要在多線程環境中使用不是線程安全的類,則必須使用提供必要同步構造的代碼來包裝類的實例。

2

使用非線程安全的實例方法沒有任何線程問題最簡單的方法是有實例只有一個線程可見(只是不把對它的引用在靜態或其他地方,其中一個線程除了那些創建它將會訪問它)。事實上,這超過90%的時間沒有做任何特別的努力。

第二個最簡單的方法是將鎖對象與實例相關聯(無論是將它用作鎖對象,還是將它與同一範圍內的鎖對象一起使用)並確保所有訪問都正確鎖定。

隨着我們沒有這些選項,因爲沒有這樣的實例和任何線程可能調用要麼或者擦出隨時另一個靜態方法靜態方法。它甚至可能不是來自同一作者的代碼。我們也不能保證其他代碼使用我們現有的鎖對象來使用它。

因此,由於這個原因,非線程安全的靜態方法的使用非常有限;幾乎只適用於在非常有限的情況下使用的私有靜態方法,這些限制提供了一次只能由一個線程調用的保證。

因此,所有的公共靜態方法都會確保它們是線程安全的(或者在記錄它們不是線程安全的時候非常清楚,並且說明這樣一個奇怪的事情的合理性)。

事實上,你會發現有很多實例方法被記錄爲「不是線程安全的」。他們列爲「不是線程安全」的理由是:

  1. 如果作者一直沒有去確認其線程安全的長度,但最好不要聲稱他們是什麼不是100%確定關於。
  2. 在這個方向錯誤是安全的;發生的更糟糕的事情是有人添加他們自己的同步來添加他們不需要的線程安全性,這實際上不會破壞任何東西。
  3. 由於他們沒有將該方法記錄爲線程安全,因此他們可以在更高版本中自由更改爲非線程安全方法。
+0

優秀的解釋。謝謝。但不能得到這個:「使用非線程安全的實例方法,沒有任何線程問題是讓該實例只對一個線程可見」。 – Sunil 2014-09-01 16:43:27

+0

你的意思是實例是在它正在使用的線程上創建的? – Sunil 2014-09-01 16:44:09

+0

是的。我會補充一點。 – 2014-09-01 16:49:10

相關問題