使用单例设计模式时,其他方法是否需要使用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-safeatomic 数据结构,而不是在每个更新方法中设置 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操作函数(clearRecycledeleteshould be synchronized to ensure thread safety(link是关于一个Enum,但同样成立关于每个 Sinlgeton 实现):

public synchronized void RecycleEmail(Email email)