QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович
Шрифт:
Интервал:
Закладка:
Захват блокировки чтения/записи
В связи со спецификой применения блокировок чтения/записи этот объект синхронизации имеет две группы функций захвата, позволяющих по-разному регулировать доступ к защищаемому участку кода.
К первой группе относятся функции, допускающие рекурсивный захват объекта синхронизации и совместное использование участка кода. Это так называемые функции блокировки по чтению.
Вторая группа функций допускает только эксклюзивный захват объекта синхронизации и к выполнению защищаемого кода допускается только один поток. Это функции блокировки по записи.
Функции блокировки по чтениюint pthread_rwlock_rdlock(pthread_rwlock_t* rwl);
int pthread_rwlock_tryrdlock(pthread_rwlock_t* rwl);
int pthread_rwlock_timedrdlock(pthread_rwlock_t* rwlock,
const struct timespec* abs);
Эта группа функций позволяет множественный захват объекта синхронизации и одновременное исполнение защищаемого участка кода, с которым ассоциируется переменная rwl. Данная группа функций предназначена для обеспечения одновременного чтения данных, разделяемых несколькими потоками. Выполнение захвата с использованием этой группы функций будет блокировано, если объект синхронизации, на который указывает rwl, уже захвачен одной из функций эксклюзивного исполнения кода (блокировки по записи).
Первая функция в группе позволяет выполнить простой захват объекта синхронизации. При рекурсивном захвате с помощью любой из указанных функций необходимо помнить, что освобождение должно производиться столько же раз, сколько и захват.
Функция pthread_rwlock_rdlock()может возвращать следующие значения:
EOK— успешное выполнение;
EAGAIN— при первом использовании статически инициированной блокировки чтения/записи ( PTHREAD_RWLOCK_INITIALIZER) недостаточно системных ресурсов для инициализации блокировки чтения/записи;
EDEADLK— вызывающий поток уже провел эксклюзивный захват (блокировку по записи) объекта синхронизации, на который ссылается rwl, и повторный захват на чтение привел бы к полному («мертвому») блокированию потока;
EFAULT— сбой при обращении ядра к rwl;
EINVAL— rwlуказывает на неверный объект блокировки чтения/записи.
Вторая из перечисленных функций проверяет, не находится ли соответствующий объект синхронизации в эксклюзивном использовании, и если это так, она возвращает соответствующее значение без последующего ожидания освобождения объекта синхронизации.
Функция pthread_rwlock_tryrdlock()возвращает следующие значения:
EOK— успешное выполнение;
EAGAIN— при первом использовании статически инициированной блокировки чтения/записи ( PTHREAD_RWLOCK_INITIALIZER) недостаточно системных ресурсов для инициализации блокировки чтения/записи;
EBUSY— блокировка чтения/записи блокирована по записи (собственно, это и есть основной мотив использования именно этого вызова);
EDEADLK— вызывающий поток уже провел эксклюзивный захват (блокировку по записи) объекта синхронизации, на который ссылается rwl;
EFAULT— сбой при обращении ядра к rwl;
EINVAL— rwlуказывает на неверный объект блокировки чтения/записи.
Третья функция из группы предусматривает завершение блокировки ожидания освобождения объекта синхронизации при возникновении блокировки по записи или по истечении заданного тайм-аута ожидания.
Функция pthread_rwlock_timedrdlock()может возвращать следующие коды ошибки:
EAGAIN— система не может захватить блокировку по чтению, поскольку достигнуто максимальное число блокировок чтения для данного объекта; [37]
EDEADLK— вызывающий поток уже является владельцем указанного объекта синхронизации; он захватил его, используя блокировку по записи, и повторная блокировка по чтению привела бы к полному блокированию потока;
EINVAL— неверный параметр вызова: либо rwlуказывает на неинициализированный объект блокировки чтения/записи, либо время тайм-аута absзадано меньше нуля или равно или выше предельного значения 1000 миллионов;
ETIMEDOUT— не удалось захватить блокировку до истечения срока тайм-аута.
Функции блокировки по записиint pthread_rwlock_wrlock(pthread_rwlock_t* rwl);
int pthread_rwlock_trywrlock(pthread_rwlock_t* rwl);
int pthread_rwlock_timedwrlock(pthread_rwlock_t* rwlock,
const struct timespec* abs_timeout);
Функции этой группы предназначены для эксклюзивного захвата объекта синхронизации и использования его для блокирования по записи. Блокировка по записи, в отличие от блокировки по чтению, не допускает совместного исполнения защищаемого участка кода (ни пишущими, ни читающими потоками). Так же как в группе функций блокировки по чтению, в этой группе присутствуют функции простого захвата, попытки захвата и захвата с тайм-аутом ожидания освобождения.
Функция pthread_rwlock_wrlock()возвращает следующие значения:
EOK— успешное выполнение;
EAGAIN— при первом использовании статически инициированной блокировки чтения/записи ( PTHREAD_RWLOCK_INITIALIZER) недостаточно системных ресурсов для инициализации блокировки чтения/записи;
EDEADLK— вызывающий поток уже является владельцем блокировки в эксклюзивном режиме;
EFAULT— сбой при обращении ядра к rwl;
EINVAL— rwlуказывает на неверный объект блокировки чтения/записи.
Функция pthread_rwlock_trywrlock()возвращает значения:
EOK— успешное выполнение;
EAGAIN— при первом использовании статически инициированной блокировки чтения/записи ( PTHREAD_RWLOCK_INITIALIZER) недостаточно системных ресурсов для инициализации блокировки чтения/записи;
EBUSY— блокировка уже захвачена в режиме чтения или записи;