JVM如何确保线程安全使用枚举实现Singleton?

时间:2014-02-13 08:05:15

标签: java enums jvm

根据Josh Bloch的Effective Java Enum是实现Singleton模式的最佳方式。

Java enum自己负责序列化和线程安全。但我不明白怎么做。

有人可以解释一下吗?

我查看了thisthis

第二个链接提供了关于enum能够序列化的大量细节,但我没有得到关于线程安全的充分解释。

枚举中声明的方法也是线程安全的,还是需要特别注意?

2 个答案:

答案 0 :(得分:4)

static初始化程序块是使用JVM内部的Lock的单线程。即它不像其他锁一样出现在jstack跟踪中。在初始化之前,没有其他线程可以访问该类的任何内容。所有类都是如此,而不仅仅是enum

enum在编译器生成的静态初始化程序块中初始化。

  

枚举中声明的方法也是线程安全的,还是需要特别注意?

同样,enum就像常规课程一样。只有标记为synchronized的方法才会同步。注意:只添加synchronized不会使其线程安全。 ;)

虽然enum实际上是static final个实例,但您可以修改其字段,即。默认情况下,枚举上的字段不是final。您还可以使用反射和Unsafe.allocateInstance来修改类的内部结构来修改枚举。一般来说,这不是一个好主意。

来自JLS 8.9.2

  

对于名称为n的每个声明的枚举常量,枚举类型具有一个隐式声明的名为n的类型为E的公共静态最终字段。这些字段被认为是以与相应的枚举常量相同的顺序声明,在任何静态之前在枚举类型中显式声明的字段。

答案 1 :(得分:1)

枚举是静态实例,它们将在类加载时初始化。初始化后,您无法更改/修改它们。所以这是线程安全的。创建后不会修改Enum实例。

但是,除非明确声明,否则添加到枚举类的方法不带任何线程安全保证。