• Наличие множественных блокировок по чтению не препятствует (не блокирует) ни одному из потоков-читателей выполнять свои операции с ресурсом.
• Блокировка по записи может быть установлена, только если ни один поток не блокирует ресурс ни по чтению, ни по записи.
• Блокировка по записи запрещает дальнейшую блокировку ресурса (блокирует запрашивающий процесс) и по чтению, и по записи.
Функции работы с блокировками чтения/записи объявлены, как и большинство примитивов синхронизации, в заголовочном файле .
Операции с блокировками чтения/записи
Инициализация объекта блокировки
int pthread_rwlock_init(pthread_rwlock_t* rwl,
const pthread_rwlockattr_t* attr);
int pthread_rwlock_destroy(pthread_rwlock_t* rwl);
Вызов функций инициализирует/разрушает блокировку чтения/записи. При инициализации блокировки ей передается структура параметров блокировки pthread_rwlockattr_t, в которой могут устанавливаться параметры доступа к объекту из других процессов.
Вместо прямого вызова функции pthread_rwlock_init() для начальной инициализации статических блокировок чтения/записи (глобальных на уровне файла кода или пространства имен namespace либо явно описанных с квалификатором static) можно воспользоваться макросом PTHREAD_RWLOCK_INITIALIZER.
Захват блокировки чтения/записи
В связи со спецификой применения блокировок чтения/записи этот объект синхронизации имеет две группы функций захвата, позволяющих по-разному регулировать доступ к защищаемому участку кода.
К первой группе относятся функции, допускающие рекурсивный захват объекта синхронизации и совместное использование участка кода. Это так называемые функции
Вторая группа функций допускает только эксклюзивный захват объекта синхронизации и к выполнению защищаемого кода допускается только один поток. Это функции
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 указывает на неверный объект блокировки чтения/записи.