2012-07-09 105 views
0

可能重複:
How thread-safe is enum in java?的Java枚舉值子線程安全

要有一個enum類像

public enum Type 
{ 
    ONE, TWO, THREE, FOUR 
} 

是在Type.values()陣列線程安全的訪問一個for循環,例如,在一個靜態方法中?例如:

public static void process() 
{ 
    for (Type type:Type.values()) 
    { 
     // Do something 
    } 
} 

此外,如果一個定義了與這些值的任意子集的靜態數組變量,那將是線程安全至?例如:

public static final Type[] TYPES = new Type[] {TWO, THREE}; 

public static void process() 
{ 
    for (Type type:TYPES) 
    { 
     // Do something 
    } 
} 

在這兩種情況下,process()方法可以屬於不同的類比的Typeenum定義和types陣列。

此外,TYPES陣列可以在Typeenum中定義一次,並由該enum的靜態方法返回。因此,鑑於上述情況,如果多個線程同時運行process()方法,代碼是否是線程安全的(至少只是讀取TYPES數組的值)?

+0

我已經閱讀過這個問題,它與我的不一樣。 :-) – PNS 2012-07-09 18:41:17

+0

你認爲它有什麼不同?看起來和我一樣。枚舉在Java中保證是線程安全的,在運行時無法修改枚舉的值,所以可以保證迭代類型是安全的。 – jjathman 2012-07-09 18:44:30

+0

這是我想要確認的,實際上。 – PNS 2012-07-09 18:50:56

回答

1

其他人已經指出values()方法returns a new array each time,所以它是線程安全的。

然而,要回答你的第二個問題:

如果定義了這些值的任何子集靜態數組變量,那將是線程安全的?

不限public static陣列並不安全,因爲數組元素總是可變的。 也就是說,任何線程都可以將TYPES[0]更改爲任何其他Type,這在多線程的情況下是不安全的,或者甚至在單線程程序中也是如此。

更好的辦法是公開一個List<Type>,然後可以安全地使其不可變(例如,使用Collections.unmodifiableList())。

+0

我正在使用陣列以獲得最佳性能。如果該數組僅用於閱讀,它會是線程安全的嗎? – PNS 2012-07-09 18:51:29

+1

@PNS:我更喜歡在線程和內存安全方面始終保守,並且假設某些代碼正在某處執行某些語言規則時可能出現某種情況。通常,從不使用數組(*變量*)的集合,其中'List'(* values *的集合)將會執行。另見Eric Lippert的優秀文章[Arrays Considered Some Harmful](http://blogs.msdn.com/b/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx)。 – 2012-07-09 18:53:58

+0

當然你是對的,但是讀它只是安全的嗎? :-) – PNS 2012-07-09 18:55:16

1

枚舉是保證線程安全的,它們是不可變的。所以,線程不能修改枚舉的狀態。

第二種情況,當你定義爲final時,它也會是線程安全的,你不允許修改錯誤的引用。

請記住,您不能僅更改「參考」,但可以更改數組的狀態。

3

方法Type.values()每次都會返回一個新數組。它這樣做是因爲該數組是可變的,並且每次都必須返回一個新副本以保證線程安全。

+0

這就是爲什麼我想知道是否在靜態數組中重用相同的values()子集可以是線程安全的原因。 – PNS 2012-07-09 19:41:59

+0

如果您在多個線程中寫入相同的副本,這只是一個問題。如果每次調用'values()'或者不修改副本,則不會有問題。 – 2012-07-09 19:58:24

+0

是的,只讀似乎是線程安全的。 – PNS 2012-07-09 20:04:54