Ответ 1
Функция pthread_mutex_unlock() должна освобождать объект mutex, на который ссылается mutex. Но способ освобождения мьютекса зависит от атрибута типа mutex. Если есть потоки, заблокированные в объекте mutex, на которые ссылается mutex, когда вызывается pthread_mutex_unlock(), в результате чего становится доступным мьютекс, политика планирования должна определять, какой поток должен получить мьютекс.
Если тип мьютекса PTHREAD_MUTEX_NORMAL, обнаружение взаимоблокировки не должно предоставляться. Попытка заблокировать мьютекс вызывает тупик. Если поток пытается разблокировать мьютекс, который он не заблокировал, или мьютекс, который разблокирован, результаты поведения undefined.
Если тип мьютекса PTHREAD_MUTEX_ERRORCHECK, то должна быть указана проверка ошибок. Если поток пытается отключить мьютекс, который он уже заблокировал, должна быть возвращена ошибка. Если поток пытается разблокировать мьютекс, который он не заблокировал, или мьютекс, который разблокирован, должна быть возвращена ошибка.
Если тип мьютекса PTHREAD_MUTEX_RECURSIVE, то мьютекс должен поддерживать концепцию количества блокировок. Когда поток успешно получает мьютекс в первый раз, счетчик блокировок должен быть установлен в единицу. Каждый раз, когда поток блокирует этот мьютекс, счетчик блокировок должен увеличиваться на единицу. Каждый раз, когда поток разблокирует мьютекс, счет блокировки должен быть уменьшен на единицу. Когда количество блокировок достигает нуля, мьютексы становятся доступными для получения других потоков. Если поток пытается разблокировать мьютекс, который он не заблокировал, или мьютекс, который разблокирован, должна быть возвращена ошибка.
Если тип мьютекса PTHREAD_MUTEX_DEFAULT, попытка рекурсивного блокирования мьютекса приводит к поведению undefined. Попытка разблокировать мьютекс, если он не был заблокирован вызывающим потоком, приводит к поведению undefined. Попытка разблокировать мьютекс, если он не заблокирован, приводит к поведению undefined.
Я обычно предпочитаю использовать мьютексы PTHREAD_MUTEX_RECURSIVE, потому что в этом случае мьютекс становится доступным, когда счетчик достигает нуля, а вызывающий поток больше не имеет блокировок этого мьютекса.