如果Singleton不是线程安全的,这到底是什么意思?

时间:2019-01-04 09:58:19

标签: 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
}

已经使用过几次,我对此非常熟悉。但是,当我深入探讨该主题时,发现该版本根本不是线程安全的。

这到底是什么意思?如果有多个线程访问它并创建一个新实例,会创建更多不同的实例吗?还是“安全”不再存在?

非常感谢您的回答。

2 个答案:

答案 0 :(得分:4)

如果您不太幸运,则可以同时存在更多实例,这样它们就可以同时访问,因此两个线程都可以同时经过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的监视器中是否已有另一个线程,因此初始化了单例。

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

答案 1 :(得分:1)

假设多个线程尝试获取单例类的实例,它们同时调用以下方法:

public static ClassSingleton getInstance() {
        if(INSTANCE == null) {
            INSTANCE = new ClassSingleton();
        }
    return INSTANCE;
}

INSTANCE == null对于两个线程都是正确的,并且它们最终都将创建一个新实例。