Блокировка чтения-записи реализуется с помощью объектов типа pthread_rwlock_t. Этотже тип имеет атрибутный объект, который инкапсулирует атрибуты объекта блокировки. Функции установки и чтения атрибутов перечислены в табл. 5.5.
Объект типа pthread_rwlock_tможет быть закрытым (для разделения между потоками одного процесса) или разделяемым (для разде л ения между потоками различных процессов).
Таблица 5.4. Операции, используемые для блокировки ч т ения-записи
Операции
Инициализация
• int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
Запрос на блокировку
• int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
• int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
• int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
• int pthread_rwlock_timedwrlock( pthread_rwlock_t | *restrict rwlock, const struct timespec *restrict abs_timeout);
Освобождение блокировки
• int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
Тестирование блокировки
• int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
• int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
Разрушение
• int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
Таблица 5.5. Функции доступа к атрибутному объекту типа pthread_rwlock_t
• int pthread_rwlockattr_init(pthread_rwlockattr_t * attr); Инициализирует атрибутный объект блокировки чтения-записи,заданный параметром attr , значениями, действующими по умолчанию для всех атрибутов, определенных реализацией
• int pthread_rwlockattr_destroy(pthread_rwlockattr_t * attr) Разрушает атрибутный объект б л окировки чтения-записи,заданный параметром attr Его можно инициализировать повторно, вызвав функцию pthread_rwlockattr_init ()
• int pthread_rwlockattr_setpshared(pthread_rwlockattr_t * attr, int pshared); int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * restrict attr, int *restrict pshared); Устанавливает или возвращает атрибут process-shared атрибутного объекта блокировки чтения-записи, заданного параметром attr . Параметр pshared может содержать следующие значения:
• PTHREAD_PROCESS_SHARED(разрешает б л окировку чтения-записи, разделяемую любыми потоками, которые имеют доступ к памяти, выделенной для этого объекта блокировки, даже если потоки принадлежат различным процессам);
• PTHREAD_PROCESS_PRIVATE(блокировка чтения-записи разделяется между потоками одного процесса)
Использование блокировок чтения-записи для реализации стратегии доступа
Блокировки чтения-записи можно использовать для реализации стратегии доступа CREW (параллельное чтение и исключающая запись). Согласно этой стратегии возможность параллельно считывать данные может быть предоставлена сразу нескольким задачам, но только одна задача получит право доступа для записи. При выполнении монопольной записи в этом случае не будет дано разрешение на параллельное чтение данных. Использование блокировок чтения-записи для защиты критических разделов продемонстрировано в листинге 5.3.
// Листинг 5.3. Пример использования потоками блокировок
// чтения-записи
//...
pthread_t ThreadA, ThreadB, ThreadC, ThreadD ; pthread_rwlock_t RWLock;
void *producerl(void *X) {
pthread_rwlock_wrlock(&RWLock) ; // Критический раэдел.
pthread_rwlock_unlock(&RWLock) ; return(0);
}
void *producer2 (void *X) {
pthread_rwlock_wrlock(&RWLock) ; // Критический раздел.
pthread_rwlock_unlock(&RWLock) ;
}
void *consumerl(void *X) {
pthread_rwlock_rdlock(&RWLock); // Критический раздел.
pthread_rwlock_unlock(&RWLock); return(0);
}
void *consumer2(void *X) {
pthread_rwlock_rdlock(&RWLock); // Критический раздел.
pthread_rwlock__unlock(&RWLock); return(0);
}
int main(void) {
pthread_rwlock_init(&RWLock,NULL); // Устанавливаем атрибуты мьютекса. pthread_create(&ThreadA, NULL, producerl, NULL) pthread_create(&ThreadB, NULL, consumerl, NULL) pthread_create(&ThreadC,NULL,producer2,NULL) pthread_create(&ThreadD,NULL, consumer2,NULL) //.. .
return(0);
}
В листинге 5.3 создаются четыре потока. Два потока, ThreadA и ThreadC, выполняют роль изготовителей, а остальные два (ThreadB и ThreadD) — потребителей. Все потоки имеют критический раздел, который защищается объектом блокировки чтения-записи RWLock. Потоки ThreadB и ThreadD могут входить в свои критические разделы параллельно или последовательно, но это исключено, если поток ThreadA или ThreadC пребывает в своем критическом разделе. Потоки ThreadA и ThreadC не могут входить в свои критические разделы параллельно. Частичная таблица решении для листинга 5.3 показана в табл. 5.6.
Таблица 5.6. Час т ич н ая таблица решений для листинга 5.3
Поток А |
Поток В |
Поток С |
Поток D |
(выполняет запись) |
(выполняет чтение) |
(выполняет запись) |
(выполняет чтение) |
Нет |
Нет |
Нет |
Да |
Нет |
Нет |
Да |
Нет |
Нет |
Да |
Нет |
Нет |
Нет |
Да |
Нет |
Да |
Да |
Нет |
Нет |
Нет |
Читать дальше