如果单例不是线程安全的,这究竟意味着什么?

Cso*_*agy 1 java singleton

我已经阅读了他对 Singleton 的基本 Java 实现,因为我将在我的课堂上介绍设计模式:

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
}
Run Code Online (Sandbox Code Playgroud)

用过几次,对它很熟悉。然而,当我深入研究这个话题时,我发现这个版本根本不是线程安全的。

这究竟是什么意思?如果多个线程访问它并创建一个新实例,是否会创建更多不同的实例?或者“安全”在哪里不复存在?

感谢您提前回答。

Epi*_*rce 5

如果您不幸同时访问它,因此两个线程同时通过,则可能存在更多实例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
}
Run Code Online (Sandbox Code Playgroud)

因为如果 的监视器内已经有另一个线程,它会强制一个线程等待lock,初始化单例。

(编辑:另外,我很高兴重复的问题是“为什么要使用 volatile”,我认为它应该是必要的,所以我添加了它 :p 否则另一个线程不会看到这个共享变量的立即更改。另一种选择的volatile将使用AtomicReference<T>。)