В чем разница между InterProcessMutex
и InterProcessSemaphoreMutex
? В документах говорится, что InterProcessSemaphoreMutex
это то же InterProcessMutex
, но не повторно входим. Но я не знаю, что означает реентерабельность.
Куратор InterProcessMutex против InterProcessSemaphoreMutex
Ответы (2)
Я главный автор Apache Curator. Независимо от того, что в документации может или не может быть сказано, я хотел бы для записи дать точные варианты использования для каждого из двух классов.
InterProcessMutex
InterProcessMutex
следует использовать, когда вам нужно иметь возможность блокировки с повторным входом. Это означает, что данный поток считается «владеющим» однажды полученной блокировкой и может заблокировать ее снова при необходимости. Это полезно, если поток передает объект блокировки другим методам, которые не должны беспокоиться о том, была ли блокировка получена или нет. Обратите внимание, что это также означает, что только поток-владелец может снять блокировку. Вот пример:
InterProcessMutex lock = new InterProcessMutex(...);
if ( !lock.acquire(...) ) ... // if acquire failed: throw, return, etc
try {
doWork(lock); // doWork() can safely call lock.acquire() again on the lock
} finally {
lock.release();
}
После получения, если блокировка снимается в другом потоке, отличном от того, который использовался для получения блокировки, IllegalMonitorStateException
бросается.
InterProcessSemaphoreMutex
InterProcessSemaphoreMutex
- это ослабленная версия блокировки, которая не учитывает поток, который ее получил. У него более простая семантика. Каждый экземпляр InterProcessSemaphoreMutex может быть получен ровно один раз и должен быть сбалансирован выпуском (в любом потоке). т.е.
InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(...);
lock.acquire();
lock.acquire(); // this will block forever
Надеюсь, это поможет. Если документы нуждаются в разъяснении, мы будем благодарны за Pull Request с улучшениями.
В этом контексте повторный вход означает, что поток может вызывать запрос для одной и той же блокировки более одного раза и не блокировать его при втором или третьем вызове. Однако он должен уравновешивать все эквайеры с одинаковым количеством выпусков. В этом сообщении на StackOverflow больше говорится о блокировках с повторным входом:
Что такое блокировка и концепция повторного входа в целом?
Специально для Curator, вот что говорится в документации о различных блокировках:
Общая блокировка повторного входа, также известная как InterProcessMutex:
public void acquire()
Получить мьютекс - блокировка, пока он не станет доступным. Примечание: тот же поток может повторно вызывать получение. Каждый вызов для приобретения должен быть уравновешен вызовом release ().
Общая блокировка (без повторного входа), также известная как InterProcessSemaphoreMutex:
public void acquire()
Получить мьютекс - блокировка, пока он не станет доступным. Должен быть уравновешен вызовом release ().
В следующем примере, если lock
была блокировкой с повторным входом, то приведенный ниже код работал бы до конца и работал бы нормально. Если lock
не было блокировкой с повторным входом, поток во время вызова второго lock.acquire()
зашел бы в тупик:
lock.acquire();
lock.acquire();
doWork();
lock.release();
lock.release();
Реентерабельные блокировки, как правило, немного дороже в реализации, но их проще использовать.
Вышеупомянутый шаблон часто встречается, когда у вас есть несколько общедоступных методов в вашем API, которые должны блокироваться, но в вашей реализации есть общедоступные методы, вызывающие другие общедоступные методы. Вы можете избежать этого, если ваши общедоступные методы выполняют блокировку и только блокировку, а затем вызывают частный метод, который предполагает, что он всегда выполняется под блокировкой; тогда ваши частные методы могут вызывать другие частные методы без необходимости захватывать блокировку более одного раза.
Отредактируйте, чтобы ответить на комментарии @ Randgalt:
InterProcessMutex куратора требует, чтобы тот же поток, который получил блокировку, освободил его. InterProcessSemaphoreMutex - нет. Может вы неправильно прочитали то, что я написал? Может я не понял? Не знаю. Во всяком случае, это так.
Это явная ложь; ни одна из блокировок не позволяет вам освободить ее от потока, отличного от потока, получившего блокировку. Более того, это по-прежнему не имеет ничего общего с вопросом «что такое повторный вход» в данном контексте - и в этом контексте повторный вход - это то, можете ли вы вызвать запрос для одной и той же блокировки более одного раза в одном потоке. .
public void release()
Выполните одно освобождение мьютекса, если вызывающий поток - тот же поток, который его получил. Если поток выполнил несколько вызовов для получения, мьютекс все равно будет удерживаться при возврате из этого метода.
InterProcessSemaphoreMutex.release ():
public void release()
Выполните один выпуск мьютекса , если вызывающий поток - тот же поток, который его получил.
Акцент добавлен. Ни одна из блокировок не позволяет вам разблокировать ее из любого потока, кроме потока, владеющего блокировкой - и это имеет смысл, потому что обе блокировки являются мьютексами, и это одно из свойств мьютекса.
release()
: Выполните один выпуск мьютекса, если вызывающий поток - тот же поток, который его получил .. Кроме того, ваше определение повторного входа делает не соответствует ни вашей собственной документации, ни каноническому определению, используемому остальной частью сообщества CS. Не вините меня за неправильную документацию и запутанные реализации.
- person antiduh; 11.10.2017