如果 Singleton 不是线程安全的,这到底意味着什么?
What does it exactly mean if a Singleton is not thread-safe?
我已经阅读了他的基本 Java 单例实现,因为我将在 class 中介绍设计模式:
public final class ClassSingleton {
private static ClassSingleton INSTANCE;
private String info = "Initial info class";
private ClassSingleton() {
}
public static ClassSingleton getInstance() {
if(INSTANCE == null) {
INSTANCE = new ClassSingleton();
}
return INSTANCE;
}
// getters and setters
}
用过几次,比较熟悉。然而,当我深入讨论这个话题时,我发现这个版本根本不是线程安全的。
这到底是什么意思?如果多个线程访问它并创建一个新的实例,是否会创建更多不同的实例?或者 "safety" 在哪里不复存在?
提前感谢您的回答。
更多的实例可以 可能 存在,如果你足够不幸,它被同时访问,所以两个线程同时通过 if(INSTANCE == null)
。
这就是为什么您通常会这样做的原因
public final class ClassSingleton {
private static volatile ClassSingleton INSTANCE;
private String info = "Initial info class";
private ClassSingleton() {
}
private static final Object lock = new Object();
public static ClassSingleton getInstance() {
if(INSTANCE == null) {
synchronized(lock) {
if(INSTANCE == null) {
INSTANCE = new ClassSingleton();
}
}
}
return INSTANCE;
}
// getters and setters
}
因为如果 lock
的监视器中已经有另一个线程,它会强制一个线程等待,初始化单例。
(编辑:另外,我很高兴重复的问题是 "why to use volatile",我认为这应该是必要的,所以我添加了它:p 否则其他线程不会立即看到此共享变量的更改. 另一个替代 volatile
的选项是使用 AtomicReference<T>
.)
假设多个线程尝试获取您的单例实例class,它们同时调用以下方法:
public static ClassSingleton getInstance() {
if(INSTANCE == null) {
INSTANCE = new ClassSingleton();
}
return INSTANCE;
}
INSTANCE == null
对两个线程都是如此,它们最终都会创建一个新实例。
我已经阅读了他的基本 Java 单例实现,因为我将在 class 中介绍设计模式:
public final class ClassSingleton {
private static ClassSingleton INSTANCE;
private String info = "Initial info class";
private ClassSingleton() {
}
public static ClassSingleton getInstance() {
if(INSTANCE == null) {
INSTANCE = new ClassSingleton();
}
return INSTANCE;
}
// getters and setters
}
用过几次,比较熟悉。然而,当我深入讨论这个话题时,我发现这个版本根本不是线程安全的。
这到底是什么意思?如果多个线程访问它并创建一个新的实例,是否会创建更多不同的实例?或者 "safety" 在哪里不复存在?
提前感谢您的回答。
更多的实例可以 可能 存在,如果你足够不幸,它被同时访问,所以两个线程同时通过 if(INSTANCE == null)
。
这就是为什么您通常会这样做的原因
public final class ClassSingleton {
private static volatile ClassSingleton INSTANCE;
private String info = "Initial info class";
private ClassSingleton() {
}
private static final Object lock = new Object();
public static ClassSingleton getInstance() {
if(INSTANCE == null) {
synchronized(lock) {
if(INSTANCE == null) {
INSTANCE = new ClassSingleton();
}
}
}
return INSTANCE;
}
// getters and setters
}
因为如果 lock
的监视器中已经有另一个线程,它会强制一个线程等待,初始化单例。
(编辑:另外,我很高兴重复的问题是 "why to use volatile",我认为这应该是必要的,所以我添加了它:p 否则其他线程不会立即看到此共享变量的更改. 另一个替代 volatile
的选项是使用 AtomicReference<T>
.)
假设多个线程尝试获取您的单例实例class,它们同时调用以下方法:
public static ClassSingleton getInstance() {
if(INSTANCE == null) {
INSTANCE = new ClassSingleton();
}
return INSTANCE;
}
INSTANCE == null
对两个线程都是如此,它们最终都会创建一个新实例。