gpt4 book ai didi

java - 这个单例模式线程安全吗?

转载 作者:搜寻专家 更新时间:2023-11-01 01:10:07 25 4
gpt4 key购买 nike

我有一个单例服务器实例,我很好奇我的代码是否是线程安全的。 I've read关于不同的单例模式,我认为通常采用的方法是 double-checked locking 模式,如下所示:

public static Singleton getInstance() {
if(singleton == null) {
synchronized(Singleton.class) {
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}

这被认为是一种设置/获取单例的高效线程安全方式。据我所知,获取和设置单例的最简单方法是 lazy instantiation,如下所示:

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

现在我想知道我的变体是否是线程安全的。我的代码:

public static void startServer(int listeningPortNumber) throws IOException {
if (server != null) {
throw new IOException("Connection exists");
}

server = new Server(listeningPortNumber);
}

我的代码与上面的惰性实例化 模式非常相似,但我看不出我的代码为何不是线程安全的。有什么我没有看到的东西或者这实际上是有效的代码吗?


引用:http://www.javaworld.com/article/2073352/core-java/simply-singleton.html

最佳答案

这不安全。

想象一下如果两个线程同时(或足够接近)调用 startServer 会发生什么:

  1. 线程 A 检查 server != null,发现 server 为 null —— 因此它不会抛出异常
  2. 线程 B 做同样的事情
  3. 线程 A 现在实例化 new Server(listeningPortNumber);
  4. 线程 B 做同样的事情,并且可能在第二次实例化时发生了不好的事情

如果 server 不是 volatile,问题会更糟,因为您甚至不再需要交错——线程 A 可能会实例化 new Server(...),但是对 server 字段的写入在很长一段时间(可能永远)都不会被线程 B 看到,因为它没有刷新到 main内存。

但由于交错,即使 servervolatile,该方法仍然很活跃。

关于java - 这个单例模式线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26661454/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com