繁体   English   中英

FileChannel和RandomAccessFile似乎不起作用

[英]FileChannel & RandomAccessFile don't seem to work

简而言之:一个使用sqlitejdbc作为后端的swing应用。 当前,启动使用同一数据库文件的多个实例没有问题。 而且应该有。 该文件已锁定(在应用运行时无法将其删除),因此检查应该很简单。 事实并非如此。

    File f = new File("/path/to/file/db.sqlite");
    FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
    System.out.println(channel.isOpen());
    System.out.println(channel.tryLock());

结果是

    true
    sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid]

无论应用程序是否正在运行。 我错过了重点吗? TIA。

FileLock是JVM独有的,而不是单个线程。 因此,如果您在与Swing应用程序相同的进程中运行该代码,则会得到该锁,因为它是由JVM共享的。

如果您的Swing应用程序未在运行,则没有其他进程在争夺该锁,因此您可以很好地获得该锁。

文件系统级别的锁与其他应用程序进行交互。 您可以从FileChannel中获得其中之一。 因此,您在示例代码中执行的操作将使该文件似乎被锁定到另一个进程,例如vi。

但是,JVM中的其他Java线程或进程将看不到该锁。 关键句是“文件锁代表整个Java虚拟机持有。它们不适合控制同一虚拟机中的多个线程对文件的访问。” 您没有看到该锁,因此您正在从与应用程序相同的JVM中运行sqlitejdbc。

因此,问题是如何查看您的JVM是否已经获取了文件锁定(假设您不控制获取该锁定的代码)? 我的一个建议是尝试在文件的另一个子集上获得排他锁,例如使用以下代码:

fc.tryLock(0L, 1L, false)

如果已经有一个锁,则应该获得OverlappingFileLockException。 这有点棘手,但可能有效。

你可以做一点实验吗? 运行该程序的两个副本(只需在睡眠状态下运行代码即可):

public class Main {
    public static void main(String [] args) throws Exception {
        File f = new File("/path/to/file/db.sqlite");
        FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
        System.out.println(channel.isOpen());
        System.out.println(channel.tryLock());
        Thread.sleep(60000);
    }
}

如果这不能锁定,则说明tryLock()在OS /驱动器/ JVM上不起作用。 如果这确实锁定了,那么您的逻辑还有其他问题。 在评论中让我们知道结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM