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

UptoLike

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

227
том, что два потока пытаются захватить оба ресурса, но запирают соот-
ветствующие мьютексы в различном порядке.
В приведенном ниже примере два потока запирают мьютексы 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);
// Поток 2:
for (; ;) {
pthread_mutex_lock(&m2);