Двоичный семафор против ReentrantLock

Я пытался понять Reentrant locks и Семафоры (вложенность Reentrant locks против механизма release/разблокировки).

Кажется, что с помощью Семафора вам нужно написать более тщательно протестированное приложение, потому что метод release() не проверяет, действительно ли поток, освобождающий разрешение, удерживает его. Когда я проверил свой тестовый код, я узнал, что это может впоследствии увеличить количество разрешений за пределы начального предела. С другой стороны, если поток не удерживает блокировку реентера, когда он вызывает метод разблокировки, мы получаем исключение IllegalMonitorException.

Так было бы правильно сказать, что нет реальной причины когда-либо иметь двоичный семафор, как все, что может сделать двоичный семафор, также может быть сделано ReentrantLock. Если мы используем двоичные семафоры, нам нужно будет проверить весь стек вызовов метода, чтобы узнать, было ли ранее получено разрешение (также оно было выпущено также, если есть возможность последующего приобретения), которое может блокироваться, если релиз его не запускает и скоро). Кроме того, поскольку реентеративные блокировки также обеспечивают одну блокировку для каждого объекта, не всегда ли лучше предпочитать блокировку реентера в двоичном семафоре?

Я проверил сообщение здесь, которое говорит о различии между двоичным семафором и мьютексом, но есть ли что-то вроде мьютекса в Java?

Спасибо, Чан.

PS - Я разместил этот вопрос на другом форуме (http://www.coderanch.com/t/615796/threads/java/reason-prefer-binary-Semaphore-Reentrant), и я еще не получил ответа. Я думал, что отправлю его сюда, чтобы посмотреть, что я могу получить.

Ответ 1

нет реальной причины когда-либо иметь двоичный семафор, как все, что может сделать двоичный семафор, также может быть сделано ReentrantLock

Если все, что вам нужно, это повторное взаимное исключение, тогда да, нет причин использовать двоичный семафор над ReentrantLock. Если по какой-либо причине вам нужна семантика без права собственности, то очевидно, что семафор - ваш единственный выбор.

Кроме того, поскольку реентеративные блокировки также обеспечивают одну блокировку для каждого объекта, не всегда ли лучше предпочитать блокировку реентера в двоичном семафоре?

Это зависит от необходимости. Как ранее объяснялось, если вам нужен простой мьютекс, тогда не выбирайте семафор. Если более чем один поток (но ограниченное число) может войти в критический раздел, вы можете сделать это через ограничение потока или семафор.

Я проверил сообщение здесь, которое говорит о различии между двоичным семафором и мьютексом, но есть ли что-то вроде мьютекса в Java?

ReentrantLock и synchronized примеры мьютексов в Java.

Ответ 2

Я не буду объяснять блокировки повторного входа, поскольку Джон уже дал хорошее объяснение выше и его пример мьютекса в java вместе с ключевым словом Synchronized.

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

Другим подходом к вашей собственной реализации мьютекса с использованием java является LockSupport. Он немного похож на Семафор, но имеет время ожидания разрешения, используя функцию park() и поддерживает только одно разрешение в то время, в отличие от Семафоров, которые поддерживают несколько из них.