FileChannel& RandomAccessFile似乎不起作用

时间:2009-02-07 23:21:56

标签: java file-io locking nio

简单来说:使用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。

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

文件系统级别锁定与其他应用程序交互。你从FileChannel得到其中一个。因此,在示例代码中执行的操作将使文件看起来锁定到另一个进程,例如vi。

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

所以问题是你如何看待你的JVM是否已经获得了对文件的锁定(假设你没有控制获取锁的代码)?我有一个建议是尝试获取文件的不同子集的独占锁,例如使用以下代码:

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

如果已经存在锁定,则应该获得OverlappingFileLockException。这有点hacky但可能有用。

答案 2 :(得分:0)

你能做一点实验吗?运行这个程序的两个副本(只是你的代码与睡眠):

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上运行。如果这确实锁定了,那么你的逻辑就会出现其他问题。请在评论中告诉我们结果。