我有一个静态类:
public class FileManager{
....
public static void writeOnFile(String something, String filepath){
File f= new File(filepath);
// Append
PrintWriter writer = new PrintWriter(new FileWriter(f, true));
writer.append(something);
}
...
}
有很多方法,上面的这个就是其中之一。
我想做的是,如果两个调用方对同一个文件进行写入,则应该在互斥的情况下进行写入。但是,当调用方写入不同的文件时,这种情况不会发生(它们不会以互斥方式写入(。
以下版本:
public class FileManager{
....
public synchronized static void writeOnFile(String something, String filepath){
File f= new File(filepath);
// Append
PrintWriter writer = new PrintWriter(new FileWriter(f, true));
writer.append(something);
}
...
}
我不认为这是我想要实现的。在这种情况下,调用方将以互斥方式进行写入,即使它们写入的文件不同。
我想问:这个第二个版本:
public class FileManager{
....
public static void writeOnFile(String something, String filepath){
File f= new File(filepath);
// Append
synchronized(f){
PrintWriter writer = new PrintWriter(new FileWriter(f, true));
writer.append(something);
}
}
...
}
会起作用吗?。如果没有,我是否必须创建一个包含每个文件的文件路径的对象,才能按照我的意愿使用锁?
同步只有在同一个实际对象上完成时才能工作。您的第二个版本将不起作用,因为它会创建一个新对象,从而创建一个新锁。您需要的是一个锁的注册表。一个小例子,使用未同步但ReentrantLock
:
private static final Map<String, Lock> LOCKS = new ConcurrentHashMap<>();
...
Lock lock = LOCKS.computeIfAbsent(filepath, p -> new ReentrantLock());
lock.lock();
try {
....
} finally {
lock.unlock();
}
每次使用相同的filepath
值调用方法时,ConcurrentHashMap
和computeIfAbsent
的组合应产生相同的Lock
对象。
另一种选择可能是使用FileLock
。它使用本机锁定机制(如果它确实存在的话(,并且基于实际的文件,而不是Java对象。