Почему не рекомендуется вызывать метод release() двоичного семафора внутри finally-clause?

Чтобы разблокировать Lock, рекомендуется вызвать метод unlock() из выражения finally:

lock.lock();
try{
  // critical section which may throw exceptions
} finally {
  lock.unlock();
}

Это делается для того, чтобы избежать возможного взаимоблокировки, если исключение выбрано из кода в критическом разделе.

Почему та же практика не рекомендуется для двоичных семафоров в эквивалентных сценариях?

mutex.acquire();
try{
  // critical section which may throw exceptions
} finally {
  mutex.release();
}

Ответ 1

Потому что нет необходимости для потока, ожидание которого на двоичном семафоре будет успешным, чтобы тот, который его сигнализирует. Нити не владеют модулями семафора, как они уже приобрели мьютексы - любой поток может сигнализировать о семафоре (отсюда их общее использование в очереди производителей-потребителей).

Ответ 2

Я бы сказал, что это лучший способ справиться с ними. Семафоры, однако, имеют возможность выпускаться отдельным потоком, поэтому в некоторых расширенных вариантах использования этот шаблон невозможен. (при этом возможно, что вызовы Lock lock() и unlock() должны быть в отдельных методах, так что блок finally также невозможен).

Ответ 3

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