POSIX позволяет мьютексам быть рекурсивными. Это означает, что один и тот же поток может блокировать один и тот же мьютекс дважды и не будет блокировать. Конечно, ему также нужно разблокировать его дважды, иначе ни один другой поток не сможет получить мьютекс. Не все системы, поддерживающие pthreads, также поддерживают рекурсивные мьютексы, но если они хотят быть POSIX соответствовать, они должны.
Другие API (API более высокого уровня) также обычно предлагают мьютексы, которые часто называются Locks. Некоторые системы/языки (например, Cocoa Objective-C) предлагают как рекурсивные, так и нерекурсивные мьютексы. Некоторые языки также предлагают только один или другой. Например. в мьютексах Java всегда рекурсивны (один и тот же поток может дважды "синхронизировать" на одном и том же объекте). В зависимости от того, какие другие функции потока они предлагают, отсутствие рекурсивных мьютексов может быть без проблем, так как они могут быть легко записаны сами (я уже реализовал рекурсивные мьютексы самостоятельно на основе более простых операций mutex/condition).
Что я действительно не понимаю: для чего нужны нерекурсивные мьютексы? Почему я хочу иметь тупик в потоке, если он дважды блокирует один и тот же мьютекс? Даже языки высокого уровня, которые могут избежать этого (например, тестирование, если это затормозит и выбрасывает исключение, если это так) обычно не делает этого. Вместо этого они будут блокировать тупик.
Это только для случаев, когда я случайно заблокировал его дважды и только разблокировал его один раз, а в случае рекурсивного мьютекса было бы труднее найти проблему, поэтому вместо этого у меня есть тупик немедленно, чтобы увидеть, где некорректная блокировка появляется? Но не мог ли я сделать то же самое с возвратом счетчика блокировки при разблокировке и в ситуации, где я уверен, что я выпустил последнюю блокировку, а счетчик не равен нулю, я могу выбросить исключение или зарегистрировать проблему? Или есть другой, более полезный случай использования нерекурсивных мьютексов, которые я не вижу? Или это может быть просто производительность, поскольку нерекурсивный мьютекс может быть немного быстрее, чем рекурсивный? Тем не менее, я тестировал это, и разница действительно не такая большая.