我有一个线程安全的单例类,我需要锁定它的方法吗?
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;
}