Исключительная блокировка файла понижается, когда закрывается другой файловый канал для заблокированного файла

#java #nio #filelock

#java #nio #блокировка файлов

Вопрос:

Я получаю эксклюзивную блокировку файла для файла, но когда я создаю другой RandomAccessFile / FileChannel для файла и закрываю его, то блокировка файла понижается, и я могу получить блокировку файла для файла из другого процесса.

Следующий воспроизводимый тест, который лучше описывает ситуацию

 final String path = "/tmp/test.lck";
int sleep = 20_000;

final File dbFile = new File(path);
RandomAccessFile raf = new RandomAccessFile(dbFile, "rw");
final FileLock envLock = raf.getChannel().tryLock(0, 1, false);
System.out.println("Lock acquired "   envLock);

//WE ACQUIRE THE LOCK
//CHECK WITH LSOF you will see
//lsof test.lck
//COMMAND  PID      USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
//java    5088     fefe    4uw  REG  253,2        0 8128854 test.lck

//FILE IS PROPERLY LOCKED, YOU CANNOT OBTAIN LOCK FROM ANOTHER PROCESS !!!! 
//you can run this same program from another terminal and you will not be able to get the lock , tryLock method will return null

System.out.println("going to sleep  "   sleep);
Thread.sleep(sleep);
System.out.println("after sleep  "   sleep);

final File dbFile2 = new File(path);
RandomAccessFile raf2 = new RandomAccessFile(dbFile2, "rw");
raf2.close();    
System.out.println("channel released and closed");

//AFTER THE CHANNEL IS CLOSED, YOU CAN OBTAIN LOCK FROM ANOTHER PROCESSS !!!! <--- HERE IS THE PROBLEM
//you can run this same program from another terminal and you will be able to get lock

//WE CLOSE THE CHANNEL
//CHECK WITH LSOF you will see
//YOU CHAN SEE THE FD CHANGE FROM uw to u
//    COMMAND  PID      USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
//    java    5088      fefe    4u  REG  253,2        0 8128854 test.lck


System.out.println("going to sleep  "   sleep);
Thread.sleep(5 * sleep);
System.out.println("after sleep  "   sleep);
 

Проблема в том, что после того, как я создаю RandomAccessFile для того же пути к файлу, для которого мне принадлежала блокировка файла, и когда я закрываю RandomAccessFile, я могу получить блокировку файла из другого процесса.
Я думаю, что это странное поведение, и это либо ошибка, либо я упускаю что-то очевидное. Как я могу правильно заблокировать файл, чтобы блокировка не была снята после последующего создания RandomAccessFile для того же файла (например
, когда я хочу проверить, удерживаю ли я блокировку и т. Д.). Я протестировал его с помощью JDK8 и JDK11 и с тем же поведением. Моя файловая система — xfs

Ответ №1:

Я не смог воспроизвести в Windows.

Из Javadoc из FileLock :

Блокировки файлов сохраняются от имени всей виртуальной машины Java.

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

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