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

时间:2015-05-31 05:36:39

标签: java multithreading locking filechannel

我想测试是否可以锁定文件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意外创建一个空文件。 OOPS !!!

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

5:进程A还检测到进程B意外创建的新文件并尝试处理它......

Bigger screenshot

http://i.imgur.com/kLMnXlz.png

这是一个使用C#的例子我想要做的事情:

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

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

1 个答案:

答案 0 :(得分:1)

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

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

  

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

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