Извините, если это тривиальный вопрос. Но я не мог найти ответ нигде. Я пишу программу, которая использует pthreads. Один поток получает блокировку (mutex), а затем пытается вставить данные в синхронизированный буфер. Буфер имеет свой собственный мьютекс, который приобретается после вызова метода push().
Если буфер заполнен и поток должен ждать условной переменной, будет ли вызов ожидания освободить все приобретенные блокировки? Или он просто освободит тот, который связан с условной переменной (которая, оказывается, является последней приобретенной блокировкой)? Если это последний, как я могу избежать взаимоблокировок, если другой поток должен получить первый замок?
Редактировать:
Проблема у меня следующая. У меня есть два потока, скажем A и B. Thread A имеет цикл for, который вставляет данные в несколько буферов. Каждая итерация вставляет элемент в один из буферов. Поскольку это поток, он непрерывно выполняет этот цикл в другом внешнем цикле для потока. Когда B активирован, он управляет этими буферами. Но B не должен работать на буферах, если A прерывается планировщиком в середине выполнения цикла for. Поэтому я использую мьютекс, чтобы заблокировать критический раздел в A, который является циклом for.
Edit-2:
Я размышлял. И ответ на мою проблему определенно не будет заключаться в том, что условная переменная буферов также освобождает первый замок. Это означало бы, что первый замок не был даже необходим в первую очередь. Если потребительские потоки (отличные от Thread B), ответственные за удаление элементов из буферов, выполняют свою работу должным образом, Thread A возобновится в какой-то момент и цикл for будет завершен. Поэтому моя проблема должна лежать там. Я присмотрюсь и уточню.
pthread_cond_wait()
освободит только мьютекс, который вы передадите ему, что в вашем случае будет мьютексом буфера, приобретенным ранее в вызове push()
.
Похоже, у вас будет возможность тупика в вашей ситуации, но это следствие вашего высокоуровневого дизайна. Если Thread B не может быть выполнен, в то время как Thread A запускает цикл for()
, но внутри цикла for()
Thread A, возможно, придется дождаться, когда Thread B будет потреблять некоторые данные для прокси-сервера, тогда взаимоблокировка неизбежна.
Для этого вам нужно будет обновить свой дизайн. Одна из возможностей - добавить функцию reserve()
к вашим синхронизированным буферам, которая резервирует пространство для последующего push()
, но не добавляет никаких данных. Затем ваш поток A может пройти и зарезервировать необходимое пространство без сохранения внешнего мьютекса (поскольку он не добавляет никаких данных, видимых для Thread B) - если ему нужно дождаться, когда Thread B будет потреблять некоторые данные, он сделает это Вот. Один из них зарезервировал все необходимое пространство, затем он может заблокировать внешний мьютекс и нажать данные - это гарантировано, что не придется ждать Thread B, потому что пространство уже зарезервировано.