The OpenNET Project
 
Поиск (ключи):    ПРОГРАММЫ СТАТЬИ СОВЕТЫ ФОРУМ
  WIKI НОВОСТИ (+) MAN'ы ДОКУМЕНТАЦИЯ

Каталог документации / Раздел "Программирование в Linux" / Оглавление документа
next up previous contents
Next: Вложенные блокировки односвязного списка Up: Синхронизация потоков Previous: Пример использования мьютексов   Contents

Иерархическая блокировка

Иногда может возникнуть необходимость доступа к нескольким ресурсам сразу. При этом возникает затруднение, когда два потока пытаются захватить оба ресурса, но запирают соответствующие мьютексы в различном порядке.

В приведенном ниже примере, два потока запирают мьютексы 1 и 2, и тогда тупик при попытке запереть другой мьютекс:

  Поток 1                             Поток 2

/* использует ресурс 1 */  |  /* использует ресурс 2 */

pthread_mutex_lock(&m1);   |  pthread_mutex_lock(&m2);

/* теперь захватывает      |  /* теперь захватывает

ресурсы 2 + 1 */           |   ресурсы 1 + 2 */

pthread_mutex_lock(&m2);   |  pthread_mutex_lock(&m1);

Наилучшим способом избежать тупика является запирание нескольких мьютексов в одном и том же порядке во всех потоках. Эта техника называется иерархической блокировкой: мьютексы упорядочиваются путем назначения каждому своего номера. После этого придерживаются правила - если мьютекс с номером 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 мог запереть его, а затем освободить оба мьютекса.



2004-06-22

АКЦИЯ! ПОДПИШИСЬ на журнал Linux Format до 31 января 2012 года и выиграй СУПЕРПРИЗ!

Журнал "Linux Format" (Линукс Формат)- Единственный в России и странах СНГ журнал на русском языке, посвящённый Linux и свободному ПО. Журнал для IT-директоров, IT-менеджеров, программистов, системных администраторов, учителей школ и преподавателей ВУЗов и всех пользователей ПК. В каждом выпуске: Новости индустрии OpenSource, обзоры новинок свободного ПО, обучающие и методические статьи.

Каждый, кто оформит подписку, получает бонус- объёмные наклейки на системный блок и подарки: с одним из первых выпусков журнала в 2012 году- диск с архивом номеров за 2005-2011 г.г. и ежемесячно электронную версию журнала в pdf-формате.

Подробнее о проведении акции вы можете прочитать на странице сайта.


  Закладки на сайте
  Проследить за страницей
Created 1996-2012 by Maxim Chirkov  
ДобавитьРекламаВебмастеруГИД  
RUNNet TopList