POSIX позволяет мьютексам быть рекурсивными. Это означает, что один и тот же поток может заблокировать один и тот же мьютекс дважды и не будет блокироваться. Конечно, он также должен разблокировать его дважды, иначе никакой другой поток не сможет получить мьютекс. Не все системы, поддерживающие потоки pthread, также поддерживают рекурсивные мьютексы, но если они хотят соответствовать POSIX, они должны это сделать .
Другие API (API более высокого уровня) также обычно предлагают мьютексы, часто называемые блокировками. Некоторые системы / языки (например, Cocoa Objective-C) предлагают как рекурсивные, так и нерекурсивные мьютексы. Некоторые языки также предлагают только один или другой. Например, в Java мьютексы всегда рекурсивны (один и тот же поток может дважды «синхронизироваться» с одним и тем же объектом). В зависимости от того, какие другие функциональные возможности потоков они предлагают, отсутствие рекурсивных мьютексов может быть проблемой, поскольку их можно легко написать самостоятельно (я сам уже реализовал рекурсивные мьютексы на основе более простых операций мьютексов / условий).
Чего я действительно не понимаю: для чего нужны нерекурсивные мьютексы? Зачем мне нужна тупиковая ситуация, если один и тот же мьютекс блокируется дважды? Даже языки высокого уровня, которые могли бы этого избежать (например, тестирование, если это приведет к взаимной блокировке, и выброс исключения, если это произойдет) обычно этого не делают. Вместо этого они позволят потоку заблокироваться.
Разве это только для случаев, когда я случайно блокирую его дважды и разблокирую только один раз, а в случае рекурсивного мьютекса будет сложнее найти проблему, поэтому вместо этого у меня сразу возникает тупик, чтобы увидеть, где появляется неправильная блокировка? Но разве я не могу сделать то же самое с возвращением счетчика блокировок при разблокировке и в ситуации, когда я уверен, что снял последнюю блокировку, а счетчик не равен нулю, я могу создать исключение или зарегистрировать проблему? Или есть какой-либо другой, более полезный вариант использования нерекурсивных мьютексов, который я не вижу? Или это может быть просто производительность, поскольку нерекурсивный мьютекс может быть немного быстрее, чем рекурсивный? Однако я проверил это, и разница действительно не так велика.