当锁定文件的另一个 FileChannnel 关闭时,文件的独占锁定被降级

Posted

技术标签:

【中文标题】当锁定文件的另一个 FileChannnel 关闭时,文件的独占锁定被降级【英文标题】:Exclusive lock on file is downgraded, when another FileChannnel for the locked file is closed 【发布时间】:2021-03-19 21:13:11 【问题描述】:

我为该文件获取了独占的 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 后,当我关闭 RandomAccessFile 时,我可以从另一个进程获取文件上的锁。 我认为这是一种奇怪的行为,要么是错误,要么是我遗漏了一些明显的东西。如何正确锁定文件,在随后为同一文件创建 RandomAccessFile 后不会释放锁定(例如 当我想检查我是否持有锁等......)。我已经使用 JDK8 和 JDK11 以及相同的行为对其进行了测试。我的文件系统是 xfs

【问题讨论】:

【参考方案1】:

我无法在 Windows 上重现。

来自the Javadoc of FileLock

代表整个 Java 虚拟机持有文件锁。

此文件锁定 API 旨在直接映射到底层操作系统的本机锁定设施。因此,文件上持有的锁应该对所有有权访问该文件的程序可见,无论这些程序是用什么语言编写的。

在某些系统上,关闭通道会释放 Java 虚拟机在底层文件上持有的所有锁,无论这些锁是通过该通道还是通过同一文件上打开的另一个通道获得的。强烈建议在程序中使用唯一通道来获取任何给定文件上的所有锁。

【讨论】:

以上是关于当锁定文件的另一个 FileChannnel 关闭时,文件的独占锁定被降级的主要内容,如果未能解决你的问题,请参考以下文章

/var/run/yum.pid 已被锁定,PID 为 XXXX 的另一个程序正在运行。

在(后退按钮、前进按钮、关闭选项卡/浏览器)上运行最后一个 Ajax 请求 [重复]

站点关闭时防止打开文件锁定

当手机处于锁定状态时,我可以用一些手势启动应用程序吗? [关闭]

当用户在 MS Access 中修改表中的另一列时,如何在 SQL Server 中将列设置为今天的日期 [关闭]

用文件中的另一个词替换特定词[关闭]