Иногда может возникнуть необходимость доступа к нескольким ресурсам сразу. При этом возникает проблема, когда два потока пытаются захватить оба ресурса, но запирают соответствующие мьютексы в различном порядке.
В этом примере, если два потока запирают мьютексы 1 и 2, то возникает тупик при попытке запереть другой мьютекс.
/* использует ресурс 1 */ /* использует ресурс 2 */
pthread_mutex_lock(&m1); pthread_mutex_lock(&m2);
/* теперь захватывает ресурсы 2 /* теперь захватывает ресурсы 1
+ 1 */ + 2 */
pthread_mutex_lock(&m2); pthread_mutex_lock(&m1);
Если блокировка всегда выполняется в указанном порядке, тупик не возникнет. Однако, эта техника может использоваться не всегда:
Иногда требуется запирать мьютексы в другом порядке, чем предписанный.
Чтобы предотвратить тупик в этой ситуации, лучше использовать функцию
pthread_mutex_trylock(). Один из потоков должен освободить
свой мьютекс, если он обнаруживает, что может возникнуть тупик.
Ниже проиллюстрирован подход условной блокировки:
Поток 1:
pthread_mutex_lock(&m2);
/* нет обработки */
pthread_mutex_unlock(&m2);
pthread_mutex_unlock(&m1);
pthread_mutex_lock(&m2);
if(pthread_mutex_trylock(&m1)==0)
/* захват! */
break;
/* уже заперт */
pthread_mutex_unlock(&m2);
}
/* нет обработки */
pthread_mutex_unlock(&m1);
pthread_mutex_unlock(&m2);