2012-07-09 101 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