Почему одна JVM дважды получает FileLock, вызывает исключение OverlappingFileLockException?

Почему двойная блокировка FileLock в одной JVM вызовет исключение OverlappingFileLockException? Почему второй замок блокировки не может быть заблокирован и получить замок, когда он будет выпущен?

4 ответа

И блокирующие методы lock(), и неблокирующие методы trylock() будут генерировать OverlappingFileLockException "Если блокировка, которая перекрывает запрашиваемую область, уже удерживается этой виртуальной машиной Java, или если другой поток уже заблокирован в этом методе и пытается заблокировать перекрывающаяся область одного и того же файла ", как описано в javadoc FileChannel.

Причина - предотвращение тупиковой ситуации. Если другой поток уже заблокирован при попытке получить эту блокировку, и вы должны были получить эту блокировку, вы можете затем попытаться получить некоторую блокировку, которую удерживает этот другой поток, что приведет к взаимоблокировке в JVM. И если блокировка, которую вы пытались получить, уже удержана, вы, возможно, уже держите другую блокировку, которую пытается получить другая нить, которая уже удерживает эту блокировку, снова приводя к взаимоблокировке - поэтому выдается исключение, чтобы вы знали вашей потенциальной ошибки кодирования. Если это произойдет при вызове tryLock(), вы не будете заблокированы, поэтому не будете иметь тупиковой ситуации, но, скорее всего, попадете в бесконечный цикл попыток получить блокировку. Вы должны получать блокировки всегда в одном и том же порядке, тогда не будет шансов на тупик, и вы не столкнетесь с этим, потому что ни один поток, пытающийся получить эту блокировку, не будет заблокирован.

Это подразумевает, что вы не должны делать lock(), tryLock() последовательно для одной и той же блокировки. Если вы уже получили блокировку, вы должны помнить об этом и не должны запрашивать ее снова.

Обратите внимание, что если какая-то другая программа уже удерживает эту блокировку, исключение не будет выдано, и tryLock() просто вернет значение null, тогда как lock() будет блокировать до тех пор, пока не сможет получить блокировку (то есть другая программа разблокировала область файла).

И нет, это не означает, что tryLock() не является потокобезопасным. Но это означает, что вам может понадобиться перехватить и обработать исключение OverlappingFilelLockException в вашем коде, даже если это не объявленное исключение.

Возможно, потому что он находится в пакете NON BLOCKING IO?:-)

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

Я сталкиваюсь с той же проблемой, это означает, что FileChannel.Lock/TryLock не является потокобезопасным. И вы должны иметь синхронизацию через блокировку FileChannel в той же JVM. Либо ReentranetLock или SingleThread конфайнмент.

Фактически, это метод, который вы вызываете для получения FileLock, который определяет, блокируется поток или нет:

  • FileChannel.lock(...) будет блокироваться, пока блокировка не будет получена.
  • FileChannel.tryLock(...) вернется немедленно, если блокировка не может быть получена.

Все это четко задокументировано в javadoc FileChannel.

Между прочим, заявленная причина @glowcoder не верна... "N" в NIO означает Новый, а не Неблокирующий. Конечно, NIO поддерживает блокирующий и неблокирующий ввод / вывод. (ОК, может быть, это была просто шутка...:-))

Другие вопросы по тегам