Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 [ 61 ] 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

ПРИМЕЧАНИЕ

Обычным примером, иллюстрирующим необходимость использования блокировок чтения-записи, является банковский счет. Считывать баланс со счета могут несколько потоков одновременно, но если какой-либо поток захочет изменить данные, ему придется подождать, пока считывающие потоки не закончат свои операции, и только после этого ему будет разрешено вносить изменения. До окончания процесса записи никакие другие процессы не должны получить доступа к счету.

Функции, описываемые в этой главе, определены стандартом Unix 98, поскольку блокировки чтения-записи не были частью стандарта Posix. 1 1996 года. Эти функции были разработаны группой производителей Unix, известной под названием Aspen Group, в 1995 году вместе с другими расширениями, которые еще не были определены Posix.l. Рабочая группа Posix (1003.1J) в настоящее время разрабатывает набор расширений Ptlireads, включающий блокировки чтения-записи, который, хочется верить, совпадет с описываемым в этой главе.

8.2. Получение и сброс блокировки чтения-записи

Блокировка чтения-записи имеет тип pthread rwl ock t. Если переменная этого типа является статической, она может быть проинициализирована присваиванием значения константы PTHREAD RWLDCK INITIALIZER.

Функция pthread rwlock rdlock позволяет заблокировать ресурс для чтения, причем вызвавший процесс будет заблокирован, если блокировка чтения-записи уже установлена записывающим процессом. Функция pthread rwlock wrlock позволяет заблокировать ресурс для записи, причем вызвавший процесс будет заблокирован, если блокировка чтения-записи уже установлена каким-либо другим процессом (считывающим или записывающим). Функция pthread rwlock unlock снимает блокировку любого типа (чтения или записи):

linclude <pthread.h>

int pthread rwlock rdlock(pthread rwlock t *rwptr): int pthread rwlock wrlock(pthread rwlock t *rwptr): int pthread rwlock unlock(pthread rwlock t *rwptr):

/* Bee функции возвращают О в случае успешного завершения, положительное значение Еххх - в случае ошибки */

Следующие две функции производят попытку заблокировать ресурс для чтения или записи, но если это невозможно, возвращают ошибку с кодом EBUSY, вместо того чтобы приостановить выполнение вызвавшего процесса:

#include <pthread.h>

int pthread rwlock tryrdlock(pthread rwlock t *rwptr): int pthread rwlock trywrlock(pthread rwlock t *rwptr):

/* Обе функции возвращают О в случае успешного завершения, положительное значение Еххх - в случае ошибки */

8.3. Атрибуты блокировки чтения-записи

Мы уже отмечали, что статическая блокировка может быть проинициализирована присваиванием ей значения PTHREAD RWLDCK INITIALIZER. Эти переменные могутбыть проинициализированы и динамически путем вызова функции pthread rwlock init.



ПРИМЕЧАНИЕ

Этот и последующие разделы данной главы содержат усложненный материал, который можно при первом чтении пропустить.

Другие реализации блокировок чтения записи заслуживают отдельного изучения. В разделе 7.1.2 книги [3] представлена реализация, в которой приоритет имеют ожидающие записи потоки и предусмотрена обработка отмены выполнения потока (о которой

Когда поток перестает нуждаться в блокировке, он может вызвать pthread rwl оск destroy:

#include <pthread.h>

int pthread rwlock init(pthread rwlock t *rwptr. const pthread rwlockattr t *attr): int pthread rwlock destroy(pthread rwlock t *rwptr):

/* Обе функции возвращают О в случае успешного завершения, положительное значение Еххх - в случае ошибки */

Если при инициализации блокировки чтения-записи attr представляет собой нулевой указатель, атрибутам присваиваются значения по умолчанию. Для присваивания атрибутам других значений следует воспользоваться двумя нижеследующими функциями:

linclude <pthread.h>

int pthread rwlockattr init(pthread rwlockattr t *attr); int pthread rwlockattr destroy(pthread rwlockattr t *attr): I* Обе функции возвращают О в случае успешного завершения, положительное значение Еххх - в случае ошибки */

После инициализации объекта типа pthread rwlockattr t для установки или сброса отдельных атрибутов используются специальные функции. Единственный определенный на настоящее время атрибут - PTHREAD PRDCESS SHARED, который указывает на то, что блокировка используется несколькими процессами, а не отдельными потоками одного процесса. Две приведенные ниже функции используются для получения и установки значения этого атрибута:

linclude <pthread.h>

int pthread rwlockattr getpshared(const pthread rwlockattr t *attr. int *valptr): int pthread rwlockattr setpshared(pthread rwlockattr t *attr, int value): /* Обе функции возвращают О в случае успешного завершения, положительное значение Еххх - в случае ошибки */

Первая функция возвращает текущее значение в целом, на которое указывает аргумент valptr. Вторая функция устанавливает значение этого атрибута равным value, которое может быть либо PTHREAD PRDCESS PRIVATE, либо PTHREAD PRDCESS SHARED.

8.4. Реализация с использованием взаимных исключений и условных переменных

Для реализации блокировок чтения-записи достаточно использовать взаимные исключения и условные переменные. В этом разделе мы рассмотрим одну из возможных реализаций, в которой предпочтение отдается ожидающим записи потокам. Это не является обязательным; возможны альтернативы.



мы вскоре будем говорить подробнее). В разделе В.18.2.3.1 стандарта IEEE 1996 [8] представлена другая реализация, в которой предпочтение имеют ожидающие записи потоки и в которой также предусмотрена обработка отмены. В главе 14 книги [12] также приводится возможная реализация, в которой приоритет имеют ожидающие записи процессы. Реализация, приведенная в этом разделе, взята из пакета АСЕ (http: www.cs.wustl.edu/-schmidt/ACE.html), автором которого является Дуг Шмидт (Doug Schmidt). Аббревиатура АСЕ означает Adaptive Communications Environment. Во всех четырех реализациях используются взаимные исключения и условные переменные.

Тип данных pthread rwlock t

в листинге 8.1 приведен текст заголовочного файла pthreadrwlock.h, в котором определен основной тип pthreadrwl ockt и прототипы функций, работающих с блокировками чтения и записи. Обычно все это находится в заголовочном файле <pthread.h>.

Листинг 8.1. Определение типа данных pthread rwlock t

my rwlock/pthread rwlock.h

1 #ifndef pthread rwlock h

2 #define pthread rwlock h

3 typedef struct {

4 pthread mutex t rw mutex; /* блокировка для структуры */

5 pthread cond t rw condreaders: /* для ждущих читающих потоков */

6 pthread cond t rw condwriters: /* для ждущих пишущих потоков */

7 int rw magic: /* для проверки ошибок */

8 int rw nwaitreaders:/* число ожидающих */

9 int rw nwaitwriters:/* число ожидающих */

10 int rw refcount:

11 /* -1. если блокировка на запись, иначе - количество блокировок на чтение */

12 } pthread rwlock t:

13 #define RW MAGIC 0x19283746

14 /* порядок должен быть такой же. как у элементов структуры */

15 #define PTHREAO RWLOCK INITIALIZER { PTHREAO MUTEX INITIALIZER. \

16 PTHREAO CONO INITIALIZER. PTHREAO CONO INITIALIZER. \

17 RW MAGIC. 0. 0. 0 }

18 typedef int pthread rwlockattr t: /* не поддерживается */

19 /* прототипы функций */

20 int pthread rwlock destroy(pthread rwlock t *):

21 int pthread rwlock init(pthread rwlock t *. pthread rwlockattr t *):

22 int pthread rwlock rdlock(pthread rwlock t *):

23 int pthread rwlock tryrdlock(pthread rwlock t *):

24 int pthread rwlock trywrlock(pthread rwlock t *):

25 int pthread rwlock unlock(pthread rwlock t *):

26 int pthread rwlock wrlock(pthread rwlock t *):



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 [ 61 ] 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.