java.io.File.createNewFile()是否在网络文件系统中是原子的?

时间:2016-10-10 17:03:41

标签: java file networking concurrency

编辑:嗯,我回来了几个月后,我试图编码的锁机制不起作用,因为createNewFile在NFS上不可靠。检查下面的答案。

以下是我的情况:我只有一个可以访问文件的应用程序,所以我对其他应用程序可能做的事情没有任何限制,但是应用程序在生产环境中的多个服务器上同时运行冗余和性能目的(有几台机器通过我们的应用程序托管每个JVM)。

基本上,我需要的是在文件夹中放置某种标志,以告诉其他实例单独保留此文件夹,因为另一个实例已在处理它。

许多搜索结果告诉您使用FileLock来实现这一目标,但我检查了Javadoc,根据我的理解,它不会有太大帮助,因为它使用托管操作系统的锁定可能性。所以我怀疑它会有多大帮助,因为有不同的托管机器。

这个问题涵盖了类似的主题:Java file locking on a network,并且接受的答案是建议实施您自己的协作锁定过程(使用OP提出的File.createNewFile())。

File.createNewFile()的Javadoc表示如果该文件尚未存在,则该过程将自动创建该文件。这在网络文件系统中是否可靠?

我的意思是,潜在的网络延迟如何同时进行存在检查和创建? :

  

检查文件是否存在以及文件的创建(如果不存在)是针对可能影响文件的所有其他文件系统活动的原子操作。

3 个答案:

答案 0 :(得分:5)

否,createNewFile在网络文件系统上无法正常工作。

即使系统调用是原子的,也仅是关于操作系统的原子,而不是通过网络。 随着时间的流逝,我发生了几次碰撞,例如每2-3个月一次(大约每60万个文件一次)。

发生的事情是我的程序在2个单独的服务器上的6个单独的实例中运行,因此我们将其称为A1,A2,A3和B1,B2,B3。
当A1,A2和A3尝试创建相同的文件时,操作系统可以正确地确保仅创建一个文件,因为该文件可以自己使用。
当A1和B1尝试在相同的确切时间创建相同的文件时,会发生某种形式的网络缓存和/或网络延迟,并且它们都会从true获得File.createNewFile()的回报。
然后,我的代码通过重命名父文件夹继续进行,以阻止程序的其他实例不必要地尝试处理该文件夹,这就是失败的地方:

  • 在A1上,文件夹重命名操作成功,但是无法删除锁定文件,因此A1允许这样,并继续处理新的传入文件夹。
  • 在B1上,文件夹重命名操作(File.renameTo(),不能做很多事情来解决它)陷入无限循环,因为该文件夹已经被重命名(根据我的说法,这还会导致大量的I / O流量) sysadmin),并且B1在重新启动程序之前无法处理任何新文件。

答案 1 :(得分:0)

  

检查文件是否存在以及文件的创建(如果不存在)是针对可能影响文件的所有其他文件系统活动的原子操作。

可以通过open()系统调用或其在我曾经使用过的任何操作系统中的等效函数轻松实现。

答案 2 :(得分:-1)

  

我的意思是,如何通过潜在的网络延迟来做到这两点   同时存在检查和创造?

同时原子之间存在差异。 Java doc并没有说这个函数是一组两个同步动作,而是两个旨在以原子方式工作的动作。如果构建此方法以原子方式执行两个操作而不是在没有先检查文件存在的情况下永远不会创建文件,并且如果文件由当前调用创建,则表示没有文件存在且文件未创建意味着存在已经是该名称的文件。

尽管呼叫在网络或本地磁盘上,但我没有理由怀疑功能是原子的还是可靠的。本地呼叫同样不可靠 - 在IO中可能出现很多问题。

当您尝试将此函数创建的空文件用作Lock时,您必须怀疑,正如D-Mac对this question的回答所解释的那样,这也是Java Doc中为此函数明确提到的内容。

你正在寻找一个目录锁和用作目录锁的空文件(以指示其他进程和线程不接触它)对我来说非常好用,只要注意写逻辑来检查文件是否存在,锁定文件清理和孤立锁。