如果不同时运行的进程中不存在而不使用锁定,如何安全地创建文件?

时间:2013-04-16 20:05:21

标签: java concurrency parallel-processing locking nio

假设两个(或更多)并发运行的Java进程需要检查文件的存在,如果它不存在则创建它,然后在运行过程中可能从该文件读取。我们希望保护自己免受多个编写者进程相互冲突和/或读取进程读取文件的不完整或不一致版本的可能性。

我们目前正在做的用于仲裁这种情况的是使用Java NIO FileLocks。一个进程设法使用FileChannel.tryLock()获取要创建的文件的独占锁并创建它,而其他并发运行的进程无法获取锁并回退到使用该文件的内存中版本他们的跑步。

但是,锁定会给我们的计算机场带来各种问题,因此我们正在探索替代方案。所以我的问题是:有没有办法安全地执行此操作而不使用文件锁?

例如,当进程发现文件不存在时,进程写入独立的临时文件,然后或多或少地“原子地”将临时文件移动到写入后的位置?在这种情况下,我们最终可能会有多个编写器进程,但如果从文件读取的任何进程始终读取一个版本或另一个版本,而不是两个或更多版本的混合,则可以。但是,我不认为所有操作系统都保证如果您打开一个文件进行阅读,即使在读取过程中被覆盖,您仍将继续阅读该文件的原始版本。

任何建议都会非常感谢!

1 个答案:

答案 0 :(得分:2)

  

假设两个(或更多)并发运行的Java进程需要检查文件的存在,如果它不存在则创建它,然后在运行过程中可能从该文件读取。

我不太了解问题的创建和阅读部分。如果您希望确保拥有唯一的文件,则可以使用new File(...).createNewFile()并检查以确保它返回true。引用Javadocs:

  

以原子方式创建一个由此抽象路径名命名的新空文件if   并且仅当具有此名称的文件尚不存在时。检查   如果文件不存在,则存在该文件并创建该文件   是一个单一的操作,相对于所有其他操作是原子的   可能影响文件的文件系统活动。

这将为您提供一个唯一的文件,只有该进程(或线程)才会“拥有”。我不确定你是怎么计划让作家知道要写哪个文件的。

如果您正在讨论创建一个您的唯一文件,然后移动到要写入的写入目录中,那么上述应该可以正常工作。完成后,您还需要在write目录中创建一个唯一的名称。

您可以使用以下内容:

private File getUniqueFile(File dir, String prefix) {
    long suffix = System.currentTimeMillis();
    while (true) {
        File file = new File(dir, prefix + suffix);
        // try creating this file, if true then it is unique
        if (file.createNewFile()) {
           return file;
        }
        // someone already has that suffix so ++ and try again
        suffix++;
    }
}

作为替代方案,您还可以使用UUID.randomUUID()或其他内容创建唯一的文件名,以生成唯一的名称。