在 Ubuntu 上的 Java 中,我使用 FileLock 来锁定文件。该问题经常发生在运行 Debian 的服务器上。为了使其易于重现,我编写了一个最小的示例应用程序(见下文)。正如您所看到的,应用程序首先锁定一个锁定文件,然后一旦成功检索锁定,它就会创建一个测试文件。在释放锁之前,它会再次删除测试文件。由于锁定的原因,永远不应该发生在成功接收锁定后测试文件已经存在的情况。但是,当(同时)运行该应用程序两次时,由于 System.gc() 调用(我需要添加该调用来重现服务器问题),锁似乎被授予了两次。这没有道理。
我使用旧版本的 Java (OpenJDK 11) 和新版本的 Java (OpenJDK 21) 测试了代码。他们提供相同的结果。
参见以下代码:
public static void main(String[] args) throws Exception {
Random rand = new Random();
while (true) {
File lockFile = new File("/tmp/lock-file");
if (!lockFile.exists()) {
lockFile.createNewFile();
}
RandomAccessFile rac = new RandomAccessFile(lockFile, "rw");
FileChannel channel = rac.getChannel();
FileLock lock = channel.tryLock();
if (lock == null) {
System.out.println("Could not get lock");
} else {
System.out.println("Got lock");
File testFile = new File("/tmp/test-file");
if (testFile.exists()) {
throw new Exception("FILE MUST NOT EXIST. LOCK PROBLEM.");
}
testFile.createNewFile();
// This helped to reproduce the server problem
System.gc();
Thread.sleep(rand.nextInt(4));
testFile.delete();
if (!lock.isValid()) {
throw new Exception("Lock is not valid anymore!");
}
lock.release();
channel.close();
rac.close();
}
Thread.sleep(rand.nextInt(4));
}
}
应用程序第一个实例的输出:
java -jar test.jar
Got lock
Got lock
Got lock
应用程序第二个实例的输出:
java -jar test.jar
Got lock
Got lock
Could not get lock
Got lock
Exception in thread "main" java.lang.Exception: FILE MUST NOT EXIST. LOCK PROBLEM.
at test.Test.main(Test.java:44)
我尝试在 Java 中使用文件锁定,我预计一个文件不能被两个进程锁定两次。然而,Java 似乎允许两次锁定文件,这对我来说是一个问题。知道出了什么问题吗?
非常感谢!
我自己找到了解决方案。我需要在 if 子句的代码块中添加以下代码
if (lock == null)
:
channel.close();
rac.close();
经过此更改,它可以完美运行。我希望这个答案能为我节省同样的时间!