使用单例设计模式时,其他方法是否需要使用synchronized关键字来保证线程安全?
When using the singleton design pattern, do other methods need to use synchronized keyword to ensure thread safety?
我想确保下面的class是线程安全的,是否应该对其他方法使用synchronized关键字?或者使用线程安全的数据结构来存储Email。我该怎么办?
public class RecycleStation {
private static volatile RecycleStation uniqueInstance;
private static List<Email> recycleEmailList ;
private RecycleStation() {
recycleEmailList = new ArrayList<>();
}
public static RecycleStation getInstance() {
if (uniqueInstance == null) {
synchronized (RecycleStation.class) {
if (uniqueInstance == null) {
uniqueInstance = new RecycleStation();
}
}
}
return uniqueInstance;
}
public void RecycleEmail(Email email) {
recycleEmailList.add(email);
}
public void deleteEmail(Email email) {
recycleEmailList.remove(email);
}
public void clear() {
recycleEmailList.clear();
}
}
最好为您的电子邮件使用 thread-safe
、atomic
数据结构,而不是在每个更新方法中设置 synchronized
。同步使用 OS 的 lock
机制,这是一个昂贵的操作,应该避免。
我会使用 ConcurrentLinkedQueue
(下面的示例)。
关于 class 本身 - 线程安全单例的 Lazy-Initialization 设计模式可能也是一个很好的解决方案。
在你的情况下,它主要是专业的:
- 您避免在
getInstance()
中使用 synchronized
- 略微缩短启动时间
- 线程安全:)
编辑: 查看 this article 以更好地理解为什么此实现是线程安全的。 @Rafael 提出了一个很好的观点:惰性初始化本身并不一定意味着线程安全。
说了这么多,下面是一个实现:
public class RecycleStation {
private static RecycleStation uniqueInstance; //You don't need `volatile` here
private static ConcurrentLinkedQueue<Email> recycleEmailList;
// Here it all begins:
private static class SingletonHolder {
private static RecycleStation instance = new RecycleStation();
}
public static RecycleStation getInstance() {
return SingletonHolder.instance;
}
private RecycleStation () {
recycleEmailList = new ConcurrentLinkedQueue<>();
}
// class functions:
public void RecycleEmail(Email email) {
recycleEmailList.add(email);
}
public void deleteEmail(Email email) {
recycleEmailList.remove(email);
}
public void clear() {
recycleEmailList = new ConcurrentLinkedQueue<>();
}
}
首先,a Singleton pattern is best implemented as Enum in Java
其次,每个email
操作函数(clear
,Recycle
,delete
)should be synchronized to ensure thread safety(link是关于一个Enum,但同样成立关于每个 Sinlgeton 实现):
public synchronized void RecycleEmail(Email email)
我想确保下面的class是线程安全的,是否应该对其他方法使用synchronized关键字?或者使用线程安全的数据结构来存储Email。我该怎么办?
public class RecycleStation {
private static volatile RecycleStation uniqueInstance;
private static List<Email> recycleEmailList ;
private RecycleStation() {
recycleEmailList = new ArrayList<>();
}
public static RecycleStation getInstance() {
if (uniqueInstance == null) {
synchronized (RecycleStation.class) {
if (uniqueInstance == null) {
uniqueInstance = new RecycleStation();
}
}
}
return uniqueInstance;
}
public void RecycleEmail(Email email) {
recycleEmailList.add(email);
}
public void deleteEmail(Email email) {
recycleEmailList.remove(email);
}
public void clear() {
recycleEmailList.clear();
}
}
最好为您的电子邮件使用 thread-safe
、atomic
数据结构,而不是在每个更新方法中设置 synchronized
。同步使用 OS 的 lock
机制,这是一个昂贵的操作,应该避免。
我会使用 ConcurrentLinkedQueue
(下面的示例)。
关于 class 本身 - 线程安全单例的 Lazy-Initialization 设计模式可能也是一个很好的解决方案。
在你的情况下,它主要是专业的:
- 您避免在
getInstance()
中使用 - 略微缩短启动时间
- 线程安全:)
synchronized
编辑: 查看 this article 以更好地理解为什么此实现是线程安全的。 @Rafael 提出了一个很好的观点:惰性初始化本身并不一定意味着线程安全。
说了这么多,下面是一个实现:
public class RecycleStation {
private static RecycleStation uniqueInstance; //You don't need `volatile` here
private static ConcurrentLinkedQueue<Email> recycleEmailList;
// Here it all begins:
private static class SingletonHolder {
private static RecycleStation instance = new RecycleStation();
}
public static RecycleStation getInstance() {
return SingletonHolder.instance;
}
private RecycleStation () {
recycleEmailList = new ConcurrentLinkedQueue<>();
}
// class functions:
public void RecycleEmail(Email email) {
recycleEmailList.add(email);
}
public void deleteEmail(Email email) {
recycleEmailList.remove(email);
}
public void clear() {
recycleEmailList = new ConcurrentLinkedQueue<>();
}
}
首先,a Singleton pattern is best implemented as Enum in Java
其次,每个email
操作函数(clear
,Recycle
,delete
)should be synchronized to ensure thread safety(link是关于一个Enum,但同样成立关于每个 Sinlgeton 实现):
public synchronized void RecycleEmail(Email email)