FileChannel & RandomAccessFile, похоже, не работает - PullRequest
2 голосов
/ 08 февраля 2009

Проще говоря: Swing-приложение, которое использует 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]

Независимо от того, запущено приложение или нет. Я упускаю суть? ТИА.

Ответы [ 3 ]

2 голосов
/ 09 февраля 2009

Блокировка уровня файловой системы взаимодействует с другими приложениями. Вы получаете один из них из FileChannel. То, что вы делаете в своем примере кода, сделает файл заблокированным для другого процесса, например, vi.

Однако другие потоки Java или процессы в JVM НЕ увидят блокировку. Ключевое предложение: «Блокировки файлов хранятся от имени всей виртуальной машины Java. Они не подходят для управления доступом к файлу несколькими потоками в одной виртуальной машине». Вы не видите блокировки поэтому вы запускаете sqlitejdbc из той же JVM, что и ваше приложение.

Итак, вопрос в том, как вы видите, установила ли ваша JVM блокировку файла (если вы не управляете кодом, получающим блокировку)? Одно из предложений, которое я хотел бы получить, это попытаться получить эксклюзивную блокировку для другого подмножества файла, например, с этим кодом:

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

Если блокировка уже есть, вы должны получить исключение OverlappingFileLockException. Это немного глупо, но может сработать.

2 голосов
/ 08 февраля 2009

FileLocks эксклюзивны для JVM, а не для отдельного потока. Таким образом, если вы запустите этот код внутри того же процесса, что и ваше приложение Swing, вы получите блокировку, потому что она используется совместно JVM.

Если ваше приложение Swing не запущено, никакой другой процесс не борется за блокировку, поэтому вы получите его там.

0 голосов
/ 09 февраля 2009

Можете ли вы провести небольшой эксперимент? Запустите две копии этой программы (только ваш код со сном):

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. Если это блокирует, то с вашей логикой что-то не так. Дайте нам знать результат в комментарии.

...