(Очевидная) тупиковая ситуация не связана напрямую с использованием семафоров.Вместо этого, здесь происходит то, что у вас есть два потока (оба из которых вы ожидаете до конца), которые оба блокируют.
Ваш первый поток действительно ожидает, чтобы семафор был доступен.
Однако второй поток в настоящее время записывает данные в STDOUT
, который в вашем случае также блокирует.Обычно это может произойти, если процесс, считывающий STDOUT
вашего процесса Ruby (например, вашего терминала), не достаточно быстр, чтобы прочитать все данные.Когда буфер канала заполнен, выполняется запись в STDOUT
блоков, в результате чего поток также не может быть активным.
Это обнаруживается Thread#join
, что приводит к возникновению исключения.
Чтобы решить эту проблему, вы можете просто убедиться, что вы читаете достаточно быстро из STDOUT
вашего процесса.Тогда я больше не мог воспроизводить проблему.
Для целей документации: я мог последовательно воспроизвести проблему, описанную OP, запустив ruby ./semaphore.rb | ruby -e "sleep 30"
с semaphore.rb
, содержащей код, показанный в вопросе.