当前位置: 首页 > 面试题库 >

Singleton中的线程安全

慕容修伟
2023-03-14
问题内容

我知道Java中的双重锁定已损坏,因此使Java中的Singletons线程安全的最佳方法是什么?我想到的第一件事是:

class Singleton{
    private static Singleton instance;

    private Singleton(){}

    public static synchronized Singleton getInstance(){
        if(instance == null) instance = new Singleton();
        return instance;
    }
}

这样行吗?如果是这样,那是否是最好的方法(我想这取决于具体情况,因此说明何时使用特定技术是最好的方法)


问题答案:

Josh Bloch建议使用单元素enum类型实现单例(请参阅 有效的Java 2nd
Edition,第3项:使用私有构造函数或枚举类型强制单例属性
)。

有人认为这是黑客,因为它并未明确传达意图,但确实有效。

以下示例直接取自本书。

public enum Elvis {
   INSTANCE;

   public void leaveTheBuilding() { ... }
}

这是他的结束语:

此方法更加简洁,免费提供了序列化机制,甚至面对复杂的序列化或反射攻击,也提供了针对多个实例的明确保证。尽管此方法尚未得到广泛采用,
但是单元素枚举类型是实现单例的最佳方法

enum恒定的单保证

[JLS

8.9。枚举](http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9)

枚举类型除了由其枚举常量定义的实例外,没有其他实例。尝试显式实例化枚举类型(第15.9.1节)是一个编译时错误。

中的final clone方法Enum确保永远不会克隆枚举常量,并且序列化机制的特殊处理确保了绝不会由于反序列化而创建重复的实例。禁止枚举类型的反射实例化。总之,这四件事确保了枚举类型的实例不存在超出枚举常量定义的实例的情况。

延迟初始化

以下代码段:

public class LazyElvis {
    enum Elvis {
        THE_ONE;
        Elvis() {
            System.out.println("I'M STILL ALIVE!!!");
        }       
    }
    public static void main(String[] args) {
        System.out.println("La-dee-daaa...");
        System.out.println(Elvis.THE_ONE);
    }
}

产生以下输出:

La-dee-daaa...
I'M STILL ALIVE!!!
THE_ONE

如您所见,THE_ONE在第一次访问常量之前,不会通过构造函数实例化常量。



 类似资料:
  • 嗯,我有三层来自控制器- 代码如下所示: 用户控制器。Java语言 用户服务。Java语言 例如,用户A和用户B同时运行相同的url,但参数不同 用户请求= 由于控制器是单例的,那么用户A的电子邮件变量是否会与用户B的电子邮件变量重叠,反之亦然? 我发现很难理解Singleton Thread-Safe在这种情况下是如何工作的。我的@Service和@Repository是否应该声明为@Scope

  • 本文向大家介绍Java线程安全的Singleton具有双重检查的锁定,包括了Java线程安全的Singleton具有双重检查的锁定的使用技巧和注意事项,需要的朋友参考一下 示例 这种类型的Singleton是线程安全的,并且可以在创建Singleton实例之后防止不必要的锁定。 Java SE 5 必须强调的是-在Java SE 5之前的版本中,上述实现是错误的,应避免使用。在Java 5之前的J

  • 我找到了关于线程安全的代码,但它没有来自给出示例的人的任何解释。我想知道为什么如果我不在“count”之前设置“synchronized”变量,那么count值将是非原子的(总是=200是期望的结果)。谢谢

  • 问题内容: 一个共同的(1,2)实现单的方式是使用具有静态构件的内部类: 据说此实现是延迟初始化的,并且是线程安全的。但是到底什么能保证其线程安全呢?处理 线程和锁的 JLS 17 并未提及静态字段具有任何类型的 事前发生 关系。如何确定初始化仅发生一次并且所有线程都看到相同的实例? 问题答案: 我们首先需要了解两点: 加载类时,静态初始化 仅 发生 一次 在声明中具有static修饰符的 字段

  • 我看到了不同的PHP二进制文件,比如非线程或线程安全? 这是什么意思? 这些软件包之间有什么区别?

  • 问题内容: 有关Singletons的维基百科文章提到了一些用线程安全的方法来用Java实现结构。对于我的问题,让我们考虑具有冗长的初始化过程并且一次被多个线程访问的Singleton。 首先,这个未提及的方法是线程安全的吗?如果是的话,它在什么上进行同步? 其次,为什么以下实现线程安全且在初始化时是懒惰的?如果两个线程同时进入该方法,到底会发生什么? 最后,在第二个示例中,如果一个线程首先获取一