Вопрос

Проще говоря: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]

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

Это было полезно?

Решение

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

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

Другие советы

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

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

Итак, вопрос в том, как вы видите, получила ли ваша 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() не работает на вашей ОС / диске / JVM.Если это действительно блокируется, значит, что-то еще не так с вашей логикой.Сообщите нам результат в комментарии.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top