Куратор InterProcessMutex против InterProcessSemaphoreMutex

В чем разница между InterProcessMutex и InterProcessSemaphoreMutex? В документах говорится, что InterProcessSemaphoreMutex это то же InterProcessMutex, но не повторно входим. Но я не знаю, что означает реентерабельность.


person Glide    schedule 09.10.2017    source источник


Ответы (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 с улучшениями.

person Randgalt    schedule 11.10.2017
comment
И ваше определение повторного вхождения не совпадает с определением, принятым сообществом. Ссылка stackoverflow.com/questions/1312259, например: Повторная блокировка - это блокировка, при которой процесс может требовать множественную блокировку. раз, не блокируя себя. - person antiduh; 12.10.2017
comment
@antiduh InterProcessMutex соответствует этому определению. Это утомительно. - person Randgalt; 12.10.2017

В этом контексте повторный вход означает, что поток может вызывать запрос для одной и той же блокировки более одного раза и не блокировать его при втором или третьем вызове. Однако он должен уравновешивать все эквайеры с одинаковым количеством выпусков. В этом сообщении на 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 - нет. Может вы неправильно прочитали то, что я написал? Может я не понял? Не знаю. Во всяком случае, это так.

Это явная ложь; ни одна из блокировок не позволяет вам освободить ее от потока, отличного от потока, получившего блокировку. Более того, это по-прежнему не имеет ничего общего с вопросом «что такое повторный вход» в данном контексте - и в этом контексте повторный вход - это то, можете ли вы вызвать запрос для одной и той же блокировки более одного раза в одном потоке. .

InterProcessMutex.release ():

public void release()
Выполните одно освобождение мьютекса, если вызывающий поток - тот же поток, который его получил. Если поток выполнил несколько вызовов для получения, мьютекс все равно будет удерживаться при возврате из этого метода.

InterProcessSemaphoreMutex.release ():

public void release()
Выполните один выпуск мьютекса , если вызывающий поток - тот же поток, который его получил.

Акцент добавлен. Ни одна из блокировок не позволяет вам разблокировать ее из любого потока, кроме потока, владеющего блокировкой - и это имеет смысл, потому что обе блокировки являются мьютексами, и это одно из свойств мьютекса.

person antiduh    schedule 09.10.2017
comment
Спасибо за отличный ответ. Невозвратная блокировка кажется более подверженной тупиковым ситуациям. Есть ли вариант использования, когда лучше использовать блокировку без повторного входа вместо блокировки с повторным входом? - person Glide; 09.10.2017
comment
Часто вы не можете снять блокировку с того же потока, который ее получил (или вам все равно). В таких случаях выбирается блокировка без повторного входа. - person Randgalt; 10.10.2017
comment
@Randgalt - это не совсем так. В этом контексте повторная входимость означает получение блокировки, а не ее освобождение. Большинство реализаций мьютексов специально запрещают ваш конкретный вариант использования; они сообщат о какой-то ошибке, если какой-либо поток, кроме потока-владельца, попытается снять блокировку, потому что это цель мьютекса - принадлежать ровно одному потоку, пока этот поток не освободит его. Ваш вариант использования будет обслуживаться чем-то вроде семафора или чего-то в этом роде. Любая попытка использовать мьютекс, как вы описали, является ошибкой, независимо от того, работает он или нет. - person antiduh; 10.10.2017
comment
InterProcessMutex @antiduh куратора требует, чтобы тот же поток, который получил блокировку, освободил его. InterProcessSemaphoreMutex - нет. Может вы неправильно прочитали то, что я написал? Может я не понял? Не знаю. Во всяком случае, это так. - person Randgalt; 11.10.2017
comment
@Randgalt - смотри мои правки; вы все равно совершенно неправы. Мало того, что повторный вход не имеет ничего общего с освобождением, ваше утверждение, что «InterProcessSemaphoreMutex не [требует освобождения из того же потока, который его получил]» полностью ложно. - person antiduh; 11.10.2017
comment
@antiduh Понятия не имею, откуда ты. Я написал InterProcessSemaphoreMutex, поэтому я почти уверен, как это работает: D Я просто дважды проверил, чтобы убедиться. Вы можете выпустить из любого потока. Кроме того, JDK ReentrantLock требует освобождения из того же потока, который получает. Взгляни. Я не понимаю, о чем вы говорите. - person Randgalt; 11.10.2017
comment
@Randgalt - тогда вам нужно обновить свою документацию, потому что InterProcessSemaphoreMutex явно говорит, и я цитирую: release(): Выполните один выпуск мьютекса, если вызывающий поток - тот же поток, который его получил .. Кроме того, ваше определение повторного входа делает не соответствует ни вашей собственной документации, ни каноническому определению, используемому остальной частью сообщества CS. Не вините меня за неправильную документацию и запутанные реализации. - person antiduh; 11.10.2017
comment
Apache Curator - это проект, поддерживаемый сообществом. Мы очень рады принять запросы на извлечение, которые исправляют ошибки в коде, документации или и то, и другое. - person Randgalt; 11.10.2017