2010-12-14 97 views
5

有些情況下,您需要擔心靜態方法是否線程安全?您何時需要擔心線程安全?

例如,如果我有靜態工具函數不觸及任何靜態類級別變量,該方法是否已經線程安全?如果我有一個接觸靜態類變量的靜態方法,該方法可能不是線程安全的嗎?

在此先感謝。

回答

6

如果我有靜態工具函數,它不會觸及任何靜態類級別的變量,那麼該方法是否已經線程安全?

大部分時間 - 重要的是如果你的方法是reentrant。像這樣的東西是折返的,因爲一切都是局部變量,每個線程接收它自己的副本:

static int add(int a, int b) 
{ 
    return a + b; 
} 

還有一些事情要小心的。如果你將一個對象傳遞給方法,並且方法改變了對象,並且在方法完成之前,你可以在另一個線程上再次調用相同的方法,但是使用相同的對象,那麼你有一個問題。

如果我有一個接觸靜態類變量的靜態方法,該方法可能不是線程安全的嗎?

主要問題再次是如果變量是可變的。如果你只是從不可變對象讀取,那麼可能沒有任何問題。

如果你調用一個方法,並且你不確定它是否可重入,並且文檔沒有說,最好假定它不是。

+0

考慮*同時*讀/寫是不夠的;如果內存不在屏障周圍同步(如JMM所記錄),則其中一個或其他線程可以觀察陳舊的值,並且即使它們實際上沒有實際衝突,寫入的值也可能會丟失。出於同樣的原因,即使只有一個編寫器線程方案在沒有某種內存障礙的情況下也會被破壞。 – 2010-12-15 04:06:42

3

只要您有多個線程訪問相同的資源,您就必須擔心線程安全問題。

如果您的靜態方法使用與其他線程相同的資源(直接或間接),即使這些資源不是靜態類變量,它也可能不安全。

+1

並且有兩種線程共享數據的靜態字段以外的其他方法。考慮靜態無效MyClass.copy(來,從)方法。 – 2010-12-14 22:59:15

2

如果沒有可變資源(例如類變量)被訪問,那麼它是線程安全的 - 但是,您必須確保您的方法不會調用訪問任何可變資源的任何其他方法。

+0

但是,即使訪問可變資源(如果訪問已同步),它也可能是線程安全的。 – 2010-12-14 22:55:31

0

如果至少有一個可以被多個線程訪問的入口點,線程安全就成爲一個問題。

如果一段代碼被多個線程訪問並正在調用其他方法/類/ etc,那麼所有的代碼樹都會變得易受攻擊。

來自「實踐中的Java併發」: 圍繞任務執行組織程序的第一步是確定合理的任務邊界。理想情況下,任務是獨立的活動:不依賴於其他任務的狀態,結果或副作用的工作不是 。獨立性促進了併發性,因爲如果存在足夠的處理資源,獨立任務可以並行執行。

例如,如果你正在編寫一個孤立的servlet,它保證由一個線程執行,你不必擔心。但是,如果您編寫由不同servlet使用的靜態實用程序,則必須處理多線程訪問。

2

只要有多個線程訪問相同的資源,您就必須擔心線程安全問題,並且這些資源不是不可變的。

2

如果您有寫入導致用戶在多個線程共享(例如,靜態變量,或多個線程使用任何物體)任何狀態的方法,那麼這個方法需要擔心線程安全,等等做任何讀取任何共享狀態的方法。

5

如果在靜態方法中只使用本地堆棧變量,那麼沒有理由擔心。 java.lang.Math.min(int,int)就是這種方法的一個很好的例子。但是,如果你觸摸任何共享的靜態變量或者具有狀態的對象(又名不可變),那麼你必須使用同步。

+0

你的意思是「沒有理由擔心」在你的第一個禮讓......? – 2010-12-14 22:57:59

+0

謝謝託尼。這是一個錯字。 – 2010-12-14 22:59:24