【问题标题】:Implementing enum-based singleton实现基于枚举的单例
【发布时间】:2015-06-22 14:27:18
【问题描述】:

J。 Bloch 在他的 Effective Java 中建议我们使用基于枚举的单例实现。例如:

public enum Application {

    INSTANCE;

    //methods, fields

}

这个实现在序列化的情况下很好,因为枚举默认为我们提供了序列化的能力(我们不必害怕在反序列化对象时得到两个不同的实例)。

我的问题是这个实现如何尊重多线程。如何使其线程安全?如果我们尝试从不同的线程访问它,我们可能会得到什么?

【问题讨论】:

  • 你让它成为线程安全的,就像你让任何其他对象成为线程安全的一样:确保对其状态的访问是正确同步的。如果它没有状态,它本质上是线程安全的。
  • 枚举的优点是它是线程安全初始化的。另一种单例模式需要一个内部类来实现相同的功能,并且更加冗长/神奇。

标签: java enums singleton


【解决方案1】:

实例化doesn't have an issue with thread safety 的实际枚举行为。但是,您需要确保实例状态本身是线程安全的。

Application 的字段和方法的交互存在风险——使用仔细的同步和锁定,或纯粹的并发数据并仔细验证不会发生其他不一致,将是您最好的选择。

【讨论】:

  • 所以还是要让枚举的一些方法同步来保证线程安全?
  • @St.Antario 是的,因为枚举中的包装状态不是线程安全的“灵丹妙药”。将其视为任何需要线程安全的类,但不要担心构造函数的线程安全(除了泄漏this)。
【解决方案2】:

Singleton 确保每个类加载器只有一个类的实例。

如果您的单例具有可变状态,您只需要注意并发性。我的意思是如果单例持久化某种可变数据。

在这种情况下,您应该使用某种同步锁定机制来防止并发修改状态和/或使用线程安全的数据结构。

【讨论】:

    最近更新 更多