线程安全单例,锁



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

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);
}

性能最好且线程安全的单例实现是William Pugh单例。你不需要同步块和ReentrantReadWriteLock

William Pugh实现确保了多线程安全性和最佳性能,因为它避免了急于创建。实际上,在类级别初始化的静态成员INSTANCE只有在类装入器装入嵌套类时才会创建,也就是说,在实际使用嵌套类时才会创建。在下面的实现中,这只能在调用getInstance()方法时发生。实际上,与EagerSingleton相反,该模型实际上允许使用封闭类而不引起急切实例化。这意味着封闭类提供的任何其他方法都可以在不初始化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,他在评论中提供了重要的澄清和评论。

1请不要在一个类中使用synchronized和Lock

如果你想使用synchronized:
private static volatile JsonWriter instance;   
private JsonWriter() {
}
public synchronized static JsonWriter getInstance() {
JsonWriter result = instance;
if (result == null) {
instance = new JsonWriter();
}
return result;
}

3或者您可以使用Locks:

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;
}