pthread_rwlock_wrlock ()

Функция pthread_rwlock_rdlock() предоставляет вызываю щ ему потоку блокировку чтения, а функция pthread_rwlock_wrlock() — блокировку записи. Запросив блокировку чтения, поток получит ее в том случае, если нет потоков, удерживающих блокировку записи. Если же таковые имеются, вызывающий поток блокируется. Если поток запросит блокировку записи, он ее получит в том случае, если нет потоков, удерживающих блокировку чтения или блокировку записи. Если же таковые имеются, вызывающий поток блокируется.

Блокировка чтения-записи реализуется с помощью объектов типа 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. Час т ич

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату