Как синхронизировать доступ к файлам в общей папке с помощью Java (ИЛИ: ReadWriteLock на сетевом уровне) - PullRequest
4 голосов
/ 26 ноября 2008

У меня есть несколько приложений, запущенных на одной виртуальной машине. У меня есть несколько виртуальных машин, работающих на одном сервере. И у меня есть несколько серверов. Все они делят файл, используя общую папку в Linux. Файл читается и пишется всеми приложениями. Во время процесса записи ни одному приложению не разрешено читать этот файл. То же самое для записи: если приложение читает файл, ни одно приложение не может его записать.

Как мне удается синхронизировать приложения, чтобы они дожидались завершения процесса записи, прежде чем читать, и наоборот? (приложения внутри виртуальной машины должны быть синхронизированы, а также приложения на серверах)

Реализация Curent использует "семафоры файлов". Если файл собирается быть записанным, приложение пытается «получить» семафор, создав дополнительный файл (назовите его «file.semaphore») в общей папке. Если файл «file.semaphore» уже существует, это означает, что семафор уже заблокирован другим приложением. У этого подхода есть проблема , из-за которой я не могу убедиться в том, что операция «файл существует» и операция «создание файла» выполняются атомарно. Таким образом, возможно, что два приложения проверят файл «file.semaphore», увидят, что он не существует, и попытаются создать файл одновременно.

Ответы [ 4 ]

3 голосов
/ 26 ноября 2008

Вы можете использовать возможности блокировки NIO. См. FileChannel # lock () .

Однако это будет работать, только если основная файловая система поддерживает блокировку по сети. Последние NFS должны поддерживать это. Возможно, Samba их тоже поддерживает, но не могу сказать наверняка.

См., Например, статью .

0 голосов
/ 14 июля 2017

Я также пытаюсь определить лучший способ решения этой проблемы для аналогичной ситуации (меньше участвующих процессов, но все та же основная проблема). Если вы не смогли использовать схему блокировки файлов, предложенную Иваном (например, система | язык | сетевой сервис не поддерживает ее), возможно, вы могли бы назначить одного из участников в качестве рефери. Все участники пишут уникальные семафоры, называют их «участник # .request», когда им нужен файл. Рефери опрашивает файловую систему для этих семафоров. Когда он его видит, он пишет обратно «участник # .lock» и удаляет запрос. Если он видит несколько одновременно, он выбирает один случайным образом (или первым по времени изменения файла) и удаляет только их запрос. Затем участник, выдавший блокировку, знает, что он может безопасно получить доступ к файлу. Когда участник завершает работу с файлом, он удаляет свою собственную блокировку. Пока есть замок, другие замки не выдаются судьей. Любые запросы, которые появляются после того, как пользователь удаляет свою блокировку, могут быть обработаны новой блокировкой без выдачи нового запроса, так что вы можете попросить других пользователей опросить их блокировку после отправки запроса. Вероятно, это то, что делает механизм блокировки в любом случае, за исключением, возможно, способности управлять блокировкой как очередью, которая поступает с запросами, обрабатываемыми в порядке их получения (то есть, если рефери использует время модификации). Кроме того, поскольку вы отвечаете за рефери, вы можете установить тайм-ауты для блокировок, позволяя ему создавать семафоры тайм-аута для процесса, который обрабатывает файл, а затем снимать блокировку (надеясь, конечно, что если этот процесс с блокировкой завершится, он сделал так красиво).

0 голосов
/ 17 октября 2014

Необходимо объединить блокировку файлов для защиты между JVM с синхронизацией внутри потоков данной JVM. См. ответ кибер-монаха здесь

0 голосов
/ 23 января 2009

Посмотрите на Javadocs для метода createNewFile () - в нем конкретно говорится, что создание файлов не является надежным методом синхронизации, и вместо этого рекомендуется класс FileLock (это другой пакет в java.nio.channels, по сути, совпадает с тем, что предлагает Иван Дубров).

Это будет означать, что ваша идентификация проблемы является точной, и никакие попытки не решат эту проблему с традиционным созданием файла. Моей первой мыслью было проверить код возврата из createNewFile (), но если Javadocs говорят, что он не подходит, то пришло время двигаться дальше.

...