Блокировка файлов Java
У меня есть несколько потоков (некоторые из них порождаются Process X, другие - Process Y, et cetera), и каждый поток должен записывать в файл MyFile
. Однако, если Thread T1
начинает сначала записывать в MyFile
, а затем, когда Thread T2
начинает писать, ему нужно дождаться T1
, чтобы освободить файл, чтобы он мог прочитать содержимое, написанное в Thread T1
, Другими словами, каждый поток будет иметь метод finalizeThread
, например:
private void finalizeThread() {
File f = new File("MyFile.dat");
f.createNewFile(); // atomically creates the file, if it doesn't exist
locked_section {
readContentsFromFile(f); // read contents if some other thread already modified the file
modifyContentsFromFile(f); // modify
writeFile(f); // write, so that new threads can see the content modified by this thread
}
}
Мой вопрос: как я могу выполнить locked_section
в приведенном выше коде? Я изучал класс FileLock
, но в Javadoc говорится, что "Блокировки файлов хранятся от имени всей виртуальной машины Java. Они не подходят для управления доступом к файлу несколькими потоками на той же виртуальной машине.".
Ответы
Ответ 1
Если файл доступен только из вашей программы, синхронизированный объект блокировки в порядке. Но если вы хотите защитить файл от изменений другими программами во время работы над ним, вы можете использовать функции блокировки файлов Java в java.nio.channels.FileLock
(пример). Как говорится в тексте, помните, что в некоторых операционных системах программы все равно могут изменять файлы, если они не проверяют наличие существующей блокировки файлов.
Ответ 2
Вместо совместного использования блокировки, возможно, у вас может быть отдельный процесс, который отвечал за сохранение блокировки файла. Чтобы начать шаг чтения/изменения/записи, Thread должен был бы спросить этот центральный процесс для блокировки через HTTP или обмен сообщениями или что угодно. Если запрос отклонен, поток перейдет в спящий режим, проснется и повторите попытку. В противном случае Thread будет читать/изменять/записывать, а затем сообщать процессу блокировки, что он освобождает блокировку.
Ответ 3
Вы хотите синхронизировать некоторые объекты. Например:
synchronized(fileLockObject) {
readContentsFromFile(f);
modifyContentsFromFile(f);
writeFile(f);
}