线程安全单例,锁

Thread safe singleton, locks

我有一个线程安全的单例class,我需要锁定它的方法吗?

        private static volatile JsonWriter instance;
private static final Object mutex = new Object();

ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

private JsonWriter() {
}

public static JsonWriter getInstance() {
    JsonWriter result = instance;
    if (result == null) {
        synchronized (mutex) {
            result = instance;
            if (result == null) {
                instance = result = new JsonWriter();
            }
        }
    }
    return result;
}

我是否需要像这样锁定每个方法以确保线程安全?

    public void write(String filePath, ArrayNode content) throws IOException {
    lock.writeLock().lock();
    File file = new File(MASTER_DIR + "/" + filePath);
    mapper.writerWithDefaultPrettyPrinter().writeValue(Files.newOutputStream(file.toPath()), content);

}

1 请不要同时使用 synchronized 和 Lock class

2 如果要使用同步:

private static volatile JsonWriter instance;   

private JsonWriter() {
}

public synchronized static JsonWriter getInstance() {
    JsonWriter result = instance;
    if (result == null) {
        instance = new JsonWriter();
    }
    return result;
}

3 或者你可以使用锁:

private static volatile JsonWriter instance;
private static final Object mutex = new Object();

ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

private JsonWriter() {}

public static JsonWriter getInstance() {
    lock.writeLock().lock();
    JsonWriter result = instance;
    if (result == null) {
       instance = result = new JsonWriter();
      }
    lock.writeLock().unlock();
    return result;
}

性能最佳且 thread-safe 的单例实现是 William Pugh Singleton。您不需要同步块和 ReentrantReadWriteLock.

William Pugh 实施确保了 multi-thread 安全和最佳性能,因为它避免了急于创建。事实上,在 class 级别初始化的静态成员 INSTANCE 只会在 class 加载程序加载嵌套 class 时创建,即当嵌套 class 将被实际使用。在下面的实现中,这只会在调用 getInstance() 方法时发生。事实上,与 EagerSingleton 相反,该模型实际上允许使用封闭的 class 而不会导致急切实例化。这意味着可以安全地使用封闭 class 提供的任何其他方法而无需初始化 INSTANCE;只有 getInstance() 方法会导致它。

您的实施可能如下所示:

class JsonWriter {

    private JsonWriter() {}

    /* ... other methods ... */

    public static JsonWriter getInstance() {
        return SingletonHelper.INSTANCE;
    }

    private static class SingletonHelper {
        private static final JsonWriter INSTANCE = new JsonWriter();
    }
}

特别感谢@Holger,他在评论中做出了重要的澄清和评论。