Если вы разрабатываете свою программу таким образом, что ни один поток не пытается заблокировать второй мьютекс, в то время как уже удерживает первый заблокированный мьютекс, то ваша программа гарантированно никогда не заблокируется.
Если вы можете 'Чтобы справиться с этим, вы все равно можете гарантировать, что ваша программа никогда не заблокируется, если вы убедитесь, что всякий раз, когда какой-либо поток пытается заблокировать более одного мьютекса за раз, он пытается заблокировать эти два (или более) мьютекса в том же порядке, что и все остальные.Поток пытается заблокировать их. (т. е. только когда поток # 1 делает lock(mutex_a); lock(mutex_b);
, а поток # 2 делает lock(mutex_b); lock(mutex_a);
, вы открываете возможность, что тупик может - и, следовательно, в конечном итоге - происходит)
Что касается того, как это сделать, если ваша программа достаточно мала, чтобы по-прежнему практично ее перепроектировать, то хорошим вариантом будет использование передачи сообщений между потоками, а не совместного использования.данные.То есть, если поток A имеет некоторые данные, о которых поток B должен знать, поток A должен обернуть эти данные в некоторый объект сообщения / события и отправить этот объект в очередь сообщений / событий, о которой поток B будет уведомлени проверить на потом.(Так как ни публикация события А, ни получение события Б никогда не будут блокироваться в течение более чем небольшого / конечного промежутка времени, при таком подходе исключается любая вероятность взаимных блокировок). Обратите внимание, что даже если объем данных, которые вы хотите передатьмежду потоками велика, этот метод все еще будет эффективен, если вы передаете данные через shared_ptr
, а не делаете копию данных.
Если, OTOH, ваша программа уже слишком велика / сложна, чтобысделать реорганизацию выполнимой, другой вариант - проанализировать и отладить причину взаимоблокировки вашей программы и внести необходимые изменения, чтобы избежать этих тупиков.Такие инструменты, как helgrind * компании Valgrind *, могут помочь с этим, автоматически обнаруживая несогласованную блокировку мьютекса во время выполнения и сообщая вам об этом.Кроме того, если вы можете перевести вашу программу в заблокированное состояние, отладчик может показать вам, где заблокирован каждый поток, и это может привести вас к пониманию того, где в вашей кодовой базе существует непоследовательный порядок блокировки, который допускает возникновение взаимоблокировки.
Кроме того, вы всегда можете снабдить каждую команду блокировкой / разблокировкой printf()
, которая включает в себя как идентификатор потока, так и уникальный идентификатор мьютекса (например, его местоположение в памяти), а затем просмотреть полученный результат.log-output для поиска противоречивых шаблонов блокировки в выходных данных.Этот анализ журнала может быть автоматизирован с помощью инструмента, если становится слишком трудно сделать это вручную.