我为文件获取独占的FileLock,但当我为文件创建另一个RandomAccessFile/FileChannel并关闭它时,FileLock会降级,我可以从另一个进程获取文件的FileLock。
以下可重复的测试更好地描述的情况
final String path = "/tmp/test.lck";
int sleep = 20_000;
final File dbFile = new File(path);
RandomAccessFile raf = new RandomAccessFile(dbFile, "rw");
final FileLock envLock = raf.getChannel().tryLock(0, 1, false);
System.out.println("Lock acquired " + envLock);
//WE ACQUIRE THE LOCK
//CHECK WITH LSOF you will see
//lsof test.lck
//COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
//java 5088 fefe 4uw REG 253,2 0 8128854 test.lck
//FILE IS PROPERLY LOCKED, YOU CANNOT OBTAIN LOCK FROM ANOTHER PROCESS !!!!
//you can run this same program from another terminal and you will not be able to get the lock , tryLock method will return null
System.out.println("going to sleep " + sleep);
Thread.sleep(sleep);
System.out.println("after sleep " + sleep);
final File dbFile2 = new File(path);
RandomAccessFile raf2 = new RandomAccessFile(dbFile2, "rw");
raf2.close();
System.out.println("channel released and closed");
//AFTER THE CHANNEL IS CLOSED, YOU CAN OBTAIN LOCK FROM ANOTHER PROCESSS !!!! <--- HERE IS THE PROBLEM
//you can run this same program from another terminal and you will be able to get lock
//WE CLOSE THE CHANNEL
//CHECK WITH LSOF you will see
//YOU CHAN SEE THE FD CHANGE FROM uw to u
// COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
// java 5088 fefe 4u REG 253,2 0 8128854 test.lck
System.out.println("going to sleep " + sleep);
Thread.sleep(5 * sleep);
System.out.println("after sleep " + sleep);
问题是,在我为我拥有FileLock的同一文件路径创建RandomAccessFile之后,当我关闭RandomAccess file时,我可以从另一个进程获取文件的锁定。我认为这是一种奇怪的行为,要么是错误,要么是我错过了一些明显的东西。如何正确锁定文件,以便在为同一文件创建RandomAccessFile后不会释放锁定(例如当我想检查我是否持有锁等…(。我已经用JDK8和JDK11测试了它,并测试了相同的行为。我的文件系统是xfs-
我无法在Windows上复制。
来自FileLock
:的Javadoc
文件锁代表整个Java虚拟机。
此文件加载API旨在直接映射到底层操作系统的本机锁定功能。因此,文件上的锁对于所有有权访问该文件的程序都应该是可见的,而不管这些程序是用什么语言编写的。
在某些系统上,关闭通道会释放Java虚拟机在底层文件上持有的所有锁,无论这些锁是通过该通道还是通过在同一文件上打开的另一个通道获取的。强烈建议在程序中使用唯一通道来获取任何给定文件的所有锁。