如果文件存在,如何锁定文件,不要创建它?

Posted

技术标签:

【中文标题】如果文件存在,如何锁定文件,不要创建它?【英文标题】:How can I lock a file if it exists, don't create it? 【发布时间】:2015-08-13 18:36:21 【问题描述】:

我想测试一下是否可以锁定文件X。如果文件不存在或无法锁定,则失败。这听起来很简单,但我总是陷入死胡同。答案的捷径是提供一种获取 FileChannel 的方法,我可以对其进行独占锁定,而不会产生任何创建文件的风险。让我解释一下……

如果没有可写的 FileChannel,我就无法使用 NIO lock(),如果不打开文件 X,我就无法获得可写的 FileChannel,如果它不存在,就会创建它。我发现的每个尝试以可写方式打开文件 X 的 Java 方法都会创建它,如果它不存在并且似乎没有办法将文件独占锁定在只读 FileChannel 上。

即使首先检查以确认文件是否存在也是有问题的。这是我最新的代码:

private LockStatus openAndLockFile(File file) 

            if (Files.notExists(file.toPath())) 
                synchronized (fileList) 
                    removeFile(file);
                
                return LockStatus.FILE_NOT_FOUND;
            
            try    
                rwFile = new RandomAccessFile(file, "rw");
                fileLock = rwFile.getChannel().lock();                  
             
            catch ...

此代码的问题在于,当NotExists 代码运行时该文件可能存在,但在new RandomAccessFile(file, "rw") 运行时已消失。这是因为我在多个线程和多个进程中运行此代码,这意味着代码必须是气密且坚如磐石的。

这是我现有代码在两个进程中运行的问题示例:

1:进程A检测到新文件

2:进程B检测到同一个文件

3:进程A处理文件并将其移动到另一个文件夹

问题 ---> 进程 B 不小心创建了一个空文件。哎呀!!!

4:进程 B 检测到进程 B 创建的新文件并对其进行处理,创建一个 0 字节的重复文件。

5:进程A也检测到进程B意外创建的新文件,并尝试对其进行处理……

Bigger screenshot

这是一个使用 C# 的示例,说明我正在尝试做的事情:

Stream iStream = File.Open("c:\\software\\code.txt", FileMode.Open,
    FileAccess.Read, FileShare.None)

非常感谢任何帮助或提示!谢谢!

【问题讨论】:

围绕关键块同步 感谢您的建议。当这段代码在完全独立的进程中运行时,它是如何工作的?可能在不同的机器上? 那么显然使用文件是错误的方法,除非文件系统在这些机器之间共享。这可能会更好:***.com/questions/1059580/distributed-lock-service 感谢您的建议,但我没有使用文件来制作分布式锁系统。我正在处理这些文件。文件锁是为了确保在任何时间点只有一个线程在处理任何给定的文件。 我正在查看完全相同的问题。你找到解决办法了吗?谢谢 【参考方案1】:

如果您试图阻止同一个应用程序(同一个 JVM)中的两个线程处理同一个文件,那么您应该使用常规 Java 锁而不是文件锁来实现这一点。文件锁被授予 JVM 并且是可重入的……所以如果一个线程“锁定”了一个文件,另一个线程可以获取同一个文件的锁。

我要做的是创建一个包含HashSet<File> 的线程安全锁定类,其中File 对象表示存在文件的绝对文件路径。然后通过锁定File 对象来实现“文件锁定”。


不幸的是,它们不仅会在不同的 JVM 中,有时还会在不同的服务器上。

在这种情况下,最好的策略可能是使用数据库来实现锁。

【讨论】:

好点。不幸的是,它们不仅会在不同的 JVM 中,有时还会在不同的服务器上。

以上是关于如果文件存在,如何锁定文件,不要创建它?的主要内容,如果未能解决你的问题,请参考以下文章

防止多次执行 Lua 脚本

创建锁定文件时防止竞争条件

vb.net 怎么判断一个文件夹或是文本文件的存在?如果没有则创建……求代码!不要VB6.0的

如果存储过程尚不存在,则创建它,但不要更改也不要删除现有的存储过程

如果它不存在,如何创建一个 CSV 文件,然后只附加到它 Python

如果创建文件不存在,如何创建目录?