Разрешение рекурсивного захвата
int pthread_mutexattr_setrecursive(
pthread_mutexattr_t* attr, int recursive);
int pthread_mutexattr_getrecursive(
const pthread_mutexattr_t* attr, int* recursive);
Функции устанавливают/считывают в атрибутной записи мьютекса признак, определяющий, может ли поток, ранее захвативший мьютекс (его владелец), захватить его еще раз (естественно, что любой другой поток захватить такой мьютекс уже не может и он будет заблокирован). Режим реализован для возможности рекурсивного вызова процедур в потоке. Необходимо помнить, что при рекурсивном захвате мьютекс должен быть освобожден столько раз, сколько раз он был захвачен. Параметр recursive может принимать следующие значения:
PTHREAD_RECURSIVE_ENABLE
— разрешает рекурсивный захват мьютекса;
PTHREAD_RECURSIVE_DISABLE
(значение по умолчанию) — запрещает рекурсивный захват мьютекса. В результате при попытке захвата мьютекса потоком, который им уже владеет, вызов pthread_mutex_lock()
не приведет к захвату мьютекса и вернет значение EDEADLK
.
Определение типа мьютекса
int pthread_mutexattr_settype(
pthread_mutexattr_t* attr, int type);
int pthread_mutexattr_gettype(
const pthread_mutexattr_t* attr, int* type);
В версиях QNX 6.2.1 и 6.3 предусматривается создание мьютексов следующих типов:
• PTHREAD_MUTEX_NORMAL
— для этого типа не проводится контроль «мертвой блокировки» (deadlock) в ситуации, когда поток, захвативший мьютекс, пытается захватить его повторно. Поэтому при попытке повторного захвата такого мьютекса тем же потоком этот поток будет безусловно блокирован (то есть он попадает в «мертвую блокировку», а это во всех случаях аварийная ситуация в выполнении приложения); такой мьютекс уже некому разблокировать (мьютекс может разблокироваться только своим владельцем). Попытка освободить (unlock) мьютекс такого типа, захваченный другим потоком, или освободить незахваченный мьютекс ни к чему не приводит, при этом не возвращается ошибка выполнения.
• PTHREAD_MUTEX_ERRORCHECK
— включается контроль ошибок. В этом режиме регистрируются следующие ситуации:
• попытка повторного захвата мьютекса тем же потоком;
• попытка освобождения мьютекса, захваченного другим потоком;
• освобождение свободного мьютекса.
• PTHREAD_MUTEX_RECURSIVE
— мьютекс, допускающий рекурсивный захват. Поток, пытающийся захватить мьютекс, уже захваченный в этом потоке, сможет это сделать, при этом количество захватов будет учитываться при освобождении мьютекса. Другой поток сможет захватить такой мьютекс только тогда, когда он будет освобожден столько же раз, сколько был захвачен. Если поток пытается освободить мьютекс, захваченный другим потоком, или свободный мьютекс, то будет возвращено сообщение об ошибке (регистрируются ошибки, предусмотренные предыдущим типом, за исключением повторного захвата, который является для рекурсивного мьютекса штатным действием).
Примечание
Обратите внимание, что разрешение рекурсивного захвата мьютекса необходимо проводить установкой двух параметров ( type
и recursive
).
• PTHREAD_MUTEX_DEFAULT
(значение по умолчанию) — попытка рекурсивного захвата мьютекса, освобождения мьютекса, захваченного другим потоком, или освобождения уже свободного мьютекса ни к чему не приводит и не возвращает ошибку выполнения.
int pthread_mutexattr_destroy(pthread_mutexattr_t* attr);
Вызов разрушает ранее применявшийся объект - атрибутную запись мьютекса, после чего она уже не может более использоваться для инициализации мьютекса без предварительного выполнения вызова pthread_mutexattr_init()
.
На этом обсуждение атрибутов заканчивается, и мы переходим непосредственно к функциям работы с мьютексом.
int pthread_mutex_init(pthread_mutex_t* mutex,
const pthread_mutexattr_t* attr);
Структура данных pthread_mutex_t
определена в файле (производный тип от типа sync_t
, который в свою очередь определен в файле ) и имеет следующий вид:
struct _sync_t {
/* Счетчик для рекурсивного мьютекса или семафора */
int count;
/* TID потока - имеет смысл и применяется только для мьютексов */
unsigned owner;
};
Функция pthread_mutex_init()
инициализирует переданный объект мьютекс в соответствии со значением переданных атрибутов. Если вместо attr
передать NULL
, то мьютекс будет создан в соответствии со значениями атрибутов по умолчанию. В native QNX API эта функция реализуется вызовом SyncTypeCreate()
. SyncTypeCreate()
— единая функция для создания всех базовых объектов синхронизации QNX Neutrino.
Читать дальше
Конец ознакомительного отрывка
Купить книгу