Почему необходимо заблокировать мьютекс перед вызовом pthread_cond_wait?
Потому что в противном случае есть неизбежное состояние гонки.
Мьютекс защищает общее состояние. Переменная условия связана с некоторым предикатом («условием») состояния. Основная идея заключается в том, что вы хотите:
1) проверить предикат
2) если предикат ложен, ложитесь спать, пока он не станет истинным
В параллельной системе некоторый поток всегда может сделать предикат истинным между (1) и (2). Чтобы избежать этой гонки, вы должны удерживать мьютекс перед (1), и вы должны разблокировать его атомарно, как вы выполняете (2).
Например, для очереди предикатом может быть «очередь не пуста». Но между временем, когда вы проверяете, не является ли очередь непустой, и временем, когда вы засыпаете, какой-то другой поток может что-то добавить в очередь.
Таким образом, вы должны удерживать мьютекс как при проверке предиката, так и во время вызова pthread_cond_wait.
Кроме того, обязательно ли брать блокировку (на том же мьютексе) перед вызовом pthread_cond_signal?
Насколько мне известно, в этом нет фундаментальной проблемы; это только вводит потенциальную неэффективность.
Здесь опять-таки, какое бы разделяемое состояние вы ни изменяли (и, следовательно, делали предикат истинным), оно должно быть защищено мьютексом. Поэтому каждый раз, когда вы хотите сообщить о состоянии, вы все равно должны удерживать мьютекс.
Если вы освобождаете мьютекс перед тем, как сообщить об этом условии, предикат может стать ложным между действиями из-за действия какого-то другого потока. Эта гонка не вызывает сбоев, потому что любой поток, ожидающий условия, должен в любом случае дважды проверить предикат, прежде чем продолжить ... Но зачем ставить его из-за проблемы?
Итог: просто следуйте инструкциям, и вам даже не нужно думать об этих вопросах. : -)