Операционные системы. Замятин А.В - 65 стр.

UptoLike

Составители: 

65
Иерархия блокировок
Иногда может возникнуть необходимость одновременного доступа
к нескольким ресурсам. При этом возникает проблема, заключающаяся
в том, что два потока пытаются захватить оба ресурса, но запирают со-
ответствующие мьютексы в различном порядке.
В приведенном ниже примере два потока запирают мьютексы 1 и 2
и возникает тупик при попытке запереть один из мьютексов.
Таблица 3.2
Пример «тупика» для двух потоков
Поток 1 Поток 2
/* использует ресурс 1 */
pthread_mutex_lock(&m1);
/* теперь захватывает
ресурсы 2+1*/
pthread_mutex_lock(&m2);
/* использует ресурс 2 */
pthread_mutex_lock(&m2);
/* теперь захватывает
ресурсы 1+2*/
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);