2

简单来说:一个使用 sqlitejdbc 作为后端的摇摆应用程序。目前,启动使用同一数据库文件的多个实例没有问题。应该有。该文件被锁定(在应用程序运行时无法删除它),因此检查应该是微不足道的。结果不是。

    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。

4

3 回答 3

2

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

如果您的 Swing 应用程序没有运行,则没有其他进程在争夺锁,因此您将获得它。

于 2009-02-08T00:25:15.577 回答
2

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

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

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

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

如果已经有锁,你应该得到一个 OverlappingFileLockException。这有点hacky,但可能会奏效。

于 2009-02-09T08:26:49.700 回答
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() 在您的操作系统/驱动器/JVM 上不起作用。如果这确实锁定了,那么您的逻辑还有其他问题。让我们在评论中知道结果。

于 2009-02-09T08:48:16.950 回答