@bakomchik

Как с помощью java реализовать блокировку файла в файловой системе, для использования в многопоточном коде?

Проблема:
Взаимодействие с внешней системой осуществляется через файловую систему(smb).
Есть папка на файловой системе, в которую необходимо записывать файлы, далее OUTBOX. Для синхронизации доступа к OUTBOX используется файл - семафор( далее -- semFile).
Писатели(мы), для того что бы записать файл в OUTBOX должны получить блокировку на файл semFile.
Читатели(внешняя система) для чтения должны получить блокировку на файл semFile.
Количество писателей заранее не известно. Запись ведется в произвольное время, многопоточно и довольно часто.
Чтение происходит в произвольное время.
Если блокировка на файл уже взята одним потоком, другие потоки не должны пытаться взять эту блокировку, а сразу писать в OUTBOX.
Блокоровка не может быть отпущена до тех пор пока все писатели не закончат запись файлов в OUTBOX.

Ограничение -- java 6.
Собственно вопрос:
Подскажите,есть ли какие нибудь бибилиотеки с реализацией необходимого функционала или хотя бы похожего на него?
Может кто-нибудь писал подобные вещи и может поделиться опытом(я новичок в concurrency) ?
Если все таки придется писать собственный велосипед, просьба подсказать куда смотреть.
Спасибо.
  • Вопрос задан
  • 3832 просмотра
Решения вопроса 1
pi314
@pi314
Президент Солнечной системы и окрестностей
Дело в том, что гарантии блокировки файла дает (или НЕ дает), собственно, файловая система, а Ява просто довольствуется тем, что есть. Существует две принципиально разные идеологии: либо блокировка ФС таки блокирует (как в Винде), либо она носит скорее информативно-предупреждающий характер (как в Линуксе). Обе - со своими плюсами и минусами.

В Яве есть механизм доступа к этому делу, в java.nio.channels.FileLock, но что и как с его помощю удастся реализовать, прямо зависит от платформы.

В связи с этим, для решения указанной задачи существует два подхода.

Кривой, исторически-обусловленный, используется, например, в HL7 (где проблема интероперабельности разных платформ через ФС все еще актуальна) определена иная семантика семафорных файлов: семафорный файл создается ПОСЛЕ того, как файл данных освобожден пишущим процессом (т.е. наличие семафора является гарантией ОТСУТСТВИЯ блокировки). Это элементарно реализуется на Яве созданием семафорного файла во временной папке с последующим move в целевую, ибо атомарность move-а гарантируется ФС. Недостаток этого подхода в том, что на однажды освобожденный файл нельзя повторно получить блокировку, в связи с чем вся эта костыльная кухня практически не масштабируется.

Правильное, более универсальное и масштабируемое решение - вообще не использовать ФС в качестве shared memory (которая для этого, строго говоря, и не предназначена), а соединять процессы через брокер с внятным протоколом (очередь сообщений, сокеты, БД в конце концов).

Так что, если это возможно, рекомендую попытаться решить проблему на уровне переосмысления общей архитектуры системы. Если нет, то придется клепать свой платформозависимый велосипед из java.nio.* и java.util.concurrent.* (например ReentrantLock)... т.е., фактически, переизобретать эдак добрую треть JEE :)

P.S. Кстати, если это чудо должно еще и поверх smb крутиться, то я бы, лично, лучше сразу завернулся в простыню и пополз на кладбище, т.к. от smb с сетью в этом деле можно поиметь под нагрузкой еще как минимум столько же удовольствия.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@Lol4t0
Никак. Самба не даст гарантий на блокировку.

Нужна надежная система с интерфейсом ФС - используйте zookerper
Ответ написан
@moryakov
Блокоровка не может быть отпущена до тех пор пока все писатели не закончат запись файлов в OUTBOX

имхо, исходя из этого условия напрашивается очередь писателей..
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы