在多线程环境中是否可以仅通过一个线程使用单例实例?

时间:2017-01-25 11:43:23

标签: java multithreading singleton

我正在使用单例类,我有更多的线程在运行。我希望在线程1使用单例实例,线程2阻塞,线程1完成实例后,另一个线程可以使用它。

我在getInstance()中使用synchronized,但它只确保只有一个线程可以同时请求该实例。它不能确保一次只有一个线程可以一起工作。

2 个答案:

答案 0 :(得分:0)

使用回调可以使代码几乎安全:

class MySingleton {
    // no public getInstance() here

    public interface Callback {
        void doWithSingleton(MySingleton singleton);
    }

    public static synchronized void doWithSingleton (Callback cb) {
        cb.doWithSingleton(instance);
    }
}

然后使用它:

MySingleton.doWithSingleton(new Callback() {
    public void doWithSingleton(MySingleton singleton) {
        singleton.method1();
        singleton.method2();
    }
});

这样,单例知道用户何时停止使用该实例,并且可以释放锁(退出synchronized块/方法)。可以使用相同的模式来实现任何需要用户不得忘记执行的初始化和清理的任何模式。

用户只能使用给定方法中的单身人员来确保"确保"单例实例只能作为回调中的局部变量使用。请注意,这并不是完全安全的,因为您无法阻止用户将实例复制到全局变量中 - 但是用户需要花费很多精力来打破它。

答案 1 :(得分:0)

看起来像一个奇怪的要求。你仍然可以拥有像辛格尔顿提供商这样的东西来提供并收回我们正在谈论的单身人士。

即使使用静态方法也可以实现:

class SN {

private static final SN instance = new SN(....) // your thingy
private static final Lock instanceLock = ... // the lock protecting your thingy

public static SN get() {
    lock.lock()
    return instance
}

public static void giveBack(SN instance) {
    if (null != instance) {
        lock.unlock()
    }
}

}    

这里的不变量是:as long I have reference to SN object, I am keeping access to SN.instanceLock。 显然,您需要确保您的用户遵循典型的get-finally-giveBack习惯用法。

但正如其他人所建议的那样,最好是避免需要这样的设计并使单例线程安全。