#include <pthread.h>
pthread_mutex_t lock1;
pthread_mutex_t lock2;
pthread_mutex_t lock3;
void t0 (void) {
pthread_mutex_lock (&lock1);
pthread_mutex_lock (&lock2);
pthread_mutex_lock (&lock3);
pthread_mutex_unlock (&lock2);
pthread_mutex_unlock (&lock1);
pthread_mutex_unlock (&lock3);
}
void t1 (void) {
pthread_mutex_lock (&lock1);
pthread_mutex_lock (&lock2);
pthread_mutex_destroy (&lock3);
pthread_mutex_unlock (&lock2);
pthread_mutex_unlock (&lock1);
}
В этом примере после t0 задачи блокирует мьютекс- lock3, t1 задачи может уничтожить его. Разрушение происходит, если следующие события происходят последовательно:
t0 приобретает lock3.
t0 выпускает lock2.
t0 выпускает lock1.
t1 приобретает блокировку lock1 выпущен t0.
t1 приобретает блокировку lock2 выпущен t0.
t1 уничтожает lock3.
Для простоты в этом примере используется смесь автоматического и ручного обнаружения параллелизма. Задачи t0 и t1 задаются вручную как точки входа при помощи опции Tasks (-entry-points). Критические разделы реализуются через примитивы pthread_mutex_lock и pthread_mutex_unlock что программное обеспечение обнаруживает автоматически. На практике для спецификации точки входа (создания резьбы) вы будете использовать примитивы, такие как pthread_create. В следующем примере показано, как дефект может появиться при использовании pthread_create.
Коррекция - Поместите пару блокировки-разблокировки вместе в том же критическом сечении, что и разрушениеБлокировка и разрушение lock3 происходит внутри критического сечения, накладываемого lock1 и lock2, но разблокировка происходит снаружи. Одной из возможных коррекций является размещение пары блокировка-разблокировка в том же критическом сечении, что и уничтожение мьютекса. Используйте один из следующих критических разделов:
Критический разрез, накладываемый lock1 в одиночку.
Критический разрез, накладываемый lock1 и lock2.
В этом исправленном коде пара блокировки-разблокировки и разрушения помещается в критический раздел, накладываемый lock1 и lock2. Когда t0 приобретает lock1 и lock2, t1 должен дождаться их релиза, прежде чем она выполнит инструкцию pthread_mutex_destroy (&lock3);. Поэтому t1 не может уничтожить mutex lock3 в заблокированном состоянии.
#include <pthread.h>
pthread_mutex_t lock1;
pthread_mutex_t lock2;
pthread_mutex_t lock3;
void t0 (void) {
pthread_mutex_lock (&lock1);
pthread_mutex_lock (&lock2);
pthread_mutex_lock (&lock3);
pthread_mutex_unlock (&lock3);
pthread_mutex_unlock (&lock2);
pthread_mutex_unlock (&lock1);
}
void t1 (void) {
pthread_mutex_lock (&lock1);
pthread_mutex_lock (&lock2);
pthread_mutex_destroy (&lock3);
pthread_mutex_unlock (&lock2);
pthread_mutex_unlock (&lock1);
}