Иногда может возникнуть необходимость доступа к нескольким ресурсам
сразу. При этом возникает затруднение, когда два потока пытаются захватить
оба ресурса, но запирают соответствующие мьютексы в различном порядке.
В приведенном ниже примере, два потока запирают мьютексы 1 и 2, и тогда
тупик при попытке запереть другой мьютекс:
Поток 1 Поток 2
/* использует ресурс 1 */ | /* использует ресурс 2 */
Наилучшим способом избежать тупика является запирание нескольких
мьютексов в одном и том же порядке во всех потоках. Эта техника называется
иерархической блокировкой: мьютексы упорядочиваются путем назначения каждому
своего номера. После этого придерживаются правила - если мьютекс с
номером n уже заперт, то нельзя запирать мьютекс с номером,
меньшим n.
Если блокировка всегда выполняется в указанном порядке, тупик не возникнет.
Однако, эта техника может использоваться не всегда.
Иногда требуется запирать мьютексы в другом порядке, чем предписанный.
Чтобы предотвратить тупик в этой ситуации, лучше использовать функцию
pthread_mutex_trylock(). Один из потоков должен освободить
свой мьютекс, если он обнаруживает, что может возникнуть тупик.
Ниже проиллюстрирован подход условной блокировки:
Поток 1:
pthread_mutex_lock(&m1);
pthread_mutex_lock(&m2);
/* нет обработки */
pthread_mutex_unlock(&m2);
pthread_mutex_unlock(&m1);
Поток 2:
for (; ;) {
pthread_mutex_lock(&m2);
if(pthread_mutex_trylock(&m1)==0)
/* захват! */
break;
/* уже заперт */
pthread_mutex_unlock(&m2);
}
/* нет обработки */
pthread_mutex_unlock(&m1);
pthread_mutex_unlock(&m2);
В примере, поток 1 запирает мьютексы в нужном порядке, а поток
2 пытается закрыть их по-своему. Чтобы убедиться, что тупик не возникнет,
поток 2 должен аккуратно обращаться с мьютексом 1; если поток блокировался,
ожидая мьютекс, который будет освобожден, он, вероятно, только что
вызвал тупик с потоком 1. Чтобы гарантировать, что это не случится,
поток 2 вызывает pthread_mutex_trylock(), который запирает
мьютекс, если тот свободен. Если мьютекс уже заперт, поток 2 получает
сообщение об ошибке. В этом случае поток 2 должен освободить мьютекс
2, чтобы поток 1 мог запереть его, а затем освободить оба мьютекса.
Журнал "Linux Format" (Линукс Формат)- Единственный в России и странах СНГ журнал на русском языке,
посвящённый Linux и свободному ПО. Журнал для IT-директоров, IT-менеджеров, программистов, системных
администраторов, учителей школ и преподавателей ВУЗов и всех пользователей ПК. В каждом выпуске: Новости
индустрии OpenSource, обзоры новинок свободного ПО, обучающие и методические статьи.
Каждый, кто оформит подписку, получает бонус- объёмные наклейки на системный блок и подарки: с одним из
первых выпусков журнала в 2012 году- диск с архивом номеров за 2005-2011 г.г. и ежемесячно электронную
версию журнала в pdf-формате.
Подробнее о проведении акции вы можете прочитать на
странице сайта.