Самой очевидной проблемой является условие вашего ожидания l oop:
while(release_T14)
Смысл условия обратный: вы хотите дождаться CV в событие, что поток 14 не был освобожден. В противном случае T14 должен быть понятным для продолжения.
Есть также дополнительные проблемы, связанные с поведением других потоков. В частности, они не производят никакого подсчета потоков до того, как поток 14 сообщит о своем запуске. С вашим текущим кодом поток № 14 оба устанавливает has_T14_started
и проверяет release_T14
в той же критической области. Поэтому release_T14
будет оставаться 0 до тех пор, пока has_T14_started
не станет ненулевым (см. Выше), поэтому ответ на ваш вопрос
Сколько раз поток 14 будет повторять это, пока l oop где он ожидает переменную условия?
равно нет . Поток 14 никогда не будет ждать, потому что (неверное) условие его продолжения гарантированно будет выполнено в самый первый раз, когда поток 14 его тестирует.
Более того, потоки, отличные от # 14, читают общую переменную has_T14_started
снаружи защита мьютекса. Поток 14 изменяет эту общую переменную, поэтому чтение имеет неопределенное поведение. Я предполагаю, что ваша идея состоит в том, чтобы избежать блокировки мьютекса, если поток 14 уже был освобожден, но это безнадежная причина, потому что вам нужно обратиться к общим переменным, чтобы определить, был ли поток 14 освобожден (или должен был быть), и вы можете сделать это безопасно только при правильной синхронизации через мьютекс.
Предлагаемые исправления:
Избавьтесь от переменных release_T14
и has_T14_started
в целом. Вам не нужен ни один, и они просто запутывают и усложняют вещи. Избавьтесь от оператора if(T14_has_started)
и вместо этого выполните его тело безоговорочно.
Объедините две критические области в одну чуть более широкую область, заблокировав мьютекс непосредственно перед if (s->i == 14){
и разблокировав его. сразу после связанного блока else
. (Снимите блокировки и разблокировки внутри этого региона.)
Измените условие для потока 14 на
while (thread_count < 5)
Если вы имеете в виду чтобы сохранить счетчик потоков для большего количества целей, чем просто для определения, когда поток 14 может продолжаться, тогда, возможно, вы захотите переместить оператор thread_count++;
за пределы блока else
сразу после (переустановленного) вызова pthread_mutex_lock()
, чтобы поток 14 увеличивает это тоже. Затем вам также может понадобиться немного изменить условие while
.