在Java中锁定文件的存在

简短版本:为什么File.createNewFile()不能用于文件锁定? 或者更具体地说:如果用于锁定应用程序数据目录,是否会出现问题?


细节:

我想使用锁定文件保护我的应用程序数据目录:如果文件lock存在,则目录被锁定,应用程序退出并显示错误消息。 如果它不存在,将创建它并继续应用程序。 退出时,文件将被删除。

锁定将不会经常创建(即性能不是问题),并且在出现某些错误时手动删除锁定文件没有问题(即无法删除文件不成问题)。

代码看起来像这样:

 File lockFile = new File("lock"); boolean lockCreated = lockFile.createNewFile(); if (lockCreated) { // do stuff lockFile.delete(); } else { System.err.println("Lockfile exists => please retry later"); // alternative: Wait and retry eg 5 times } 

现在我对createNewFile()的Javadoc有点困惑:

当且仅当具有此名称的文件尚不存在时,以primefaces方式创建由此抽象路径名命名的新空文件。 检查文件是否存在以及文件的创建(如果不存在)是针对可能影响文件的所有其他文件系统活动的primefaces操作

注意: 此方法应用于文件锁定,因为无法使生成的协议可靠地工作。 应该使用FileLock工具。

考虑到存在检查和文件创建是primefaces的,注释中提到的潜在问题是什么?

2007年12月的这篇论坛post表明,根据File.delete()的Javadoc,存在“显着的平台差异”(尽管至少从Java SE 1.4.2开始我找不到这样的声明)。 但即使存在这样的差异:它们真的会导致锁定失败(即两个进程认为数据目录同时可用)吗?


注意:想要以下任何一项:

  • 锁定文件,以便其他进程无法访问和/或修改它(我发现的大多数信息似乎都在讨论这个问题)。
  • 确保没有其他进程可以删除锁定。
  • 同步同一JVM的多个线程(虽然我认为我的解决方案也应该能够处理它)。

简短的回答:Java中基于可靠文件的锁定是不切实际的。

答案很长:在任何操作系统中,基于文件的锁定问题总是归结为文件来自哪种存储系统。 几乎所有网络访问的文件系统(NFS,SAMBA等)都有非常不可靠(或至少是不可预测的)同步文件创建或删除,这使得一般的Java-ish方法不可取。 在某些操作系统中,使用本地文件系统,有时可以获得所需的内容。 但是您需要了解底层文件系统及其特性并谨慎处理。

Files.createFile(…)的Javadoc,自Java 7以来可用的java.nio.file一部分,重复了primefaces性的承诺,但没有提到任何关于基于文件的锁定。


我的推理:

  • 较新的方法(来自java.nio.file.Files )受到与旧版本(来自java.io.File )相同(或类似)问题的影响,而Javadoc只是缺少此信息…
  • …或者更新的方法实际上表现得更可预测和正确。

鉴于java.nio.file的error handling和规范与File类(自JDK 1.2以来一直存在)相比通常得到了改进,我假设第二种选择是正确的。


我的结论:使用Files.createFile(…)对于这个用例很好。