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

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

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

struct { /* общие данные производителя и потребителя */ int buff[NBUFF]:

sem t mutex, nempty. nstored: /* семафоры, a не указатели */ } shared:

void *produce(void *). *consume(void *): int

main(int argc. char **argv) {

pthread t tid produce. tid consume:

if (argc != 2)

err quit( usage: prodcons2 <#items> ): nitems = atoi(argv[l]):

/* инициализация трех семафоров */ Sem init(&shared.mutex. 0. 1): Sem in1t(&shared.nempty. 0. NBUFF1: Semjnit(&shared.nstored. 0, 0):

Set concurrency(2):

Pthread create(&tid produce, NULL, produce. NULL): Pthread create(&tid consume. NULL, consume. NULL);

Pthread join(tid produce. NULL); PthreadJoin(tid consume. NULL):

Sem destroy(&shared.mutex): Sem destroy(&shared.nempty); Sem destroy(&shared.nstored): exit(O):

void *

produce(void *arg) {

int i:

for (i - 0; i < nitems; i++) { Sem wait(&shared.nempty); Sem wait(&shared.mutex); shared.buff[i % NBUFF] = i: Sem post(&shared.mutex): Sem pos t (&sha red. nsto red);

return(NULL):

void *

consume(void *arg)

/* ожидание одного свободного поля */ /* помещение i в циклически! буфер */

/* поместили еще один элемент */

for (i = 0; i < nitems; i++) { Sem wait(&shared.nstored):

/* ожидаем появления хотя бы одного готового для обработки элемента */

продолжение



Листинг 10.11 (продолжение)

49 Sem wait(&shared.mutex):

50 if (shared.buff[i % NBUFF] != 1)

51 printf( buff[ d] = M\n , i, shared.buff[i % NBUFF]):

52 Sem post(&shared.mutex);

53 Sem post(&shared.nempty); /* еще одно пустое поле */

54 }

55 return(NULL);

56 }

Выделение семафоров

6 Мы объявляем три семафора типа sem t, и теперь это сами семафоры, а не указатели на них.

Вызов semjnit

16-27 Мы вызываем semjnit вместо semjpen а затем sem destroy вместо sem unl ink. Вызывать sem destroy на самом деле не требуется, поскольку программа все равно завершается.

Остальные изменения обеспечивают передачу указателей на три семафора при вызовах sem wait и sem post.

10.9. Несколько производителей, один потребитель

Решение в разделе 10.6 относится к классической задаче с одним производителем и одним потребителем. Новая, интересная модификация программы позволит нескольким производителям работать с одним потребителем. Начнем с решения из листинга 10.11, в котором использовались размещаемые в памяти семафоры. В листинге 10.12 приведены объявления глобальных переменных и функция main.

Листинг 10.12. Функция main задачи с несколькими производителями

pxsem/prodcons3.c

1 finclude unpipc.h

2 fdefine NBUFF 10

3 fdefine MAXNTHREADS 100

4 int mtems. nproducers: /* только для чтения производителем и потребителем */

5 struct { /* общие данные */

6 int buff[NBUFF];

7 int nput;

8 int nputval:

9 semj mutex, nempty. nstored: /* семафоры, a не указатели */

10 } shared;

11 void *produce(void *), *consume(vo1d *):

12 int

13 main(int argc, char **argv)



14 {

15 int i, COunt[MAXNTHREADS];

16 pthread t t1d produce[MAXNTHREADS], tid consume:

17 if (argc != 3)

18 err quit( usage; prodcons3 <#items> <#producers> );

19 nitems = atoi(argv[l]);

20 nproducers - m1n(atoi(argv[2]). MAXNTHREADS);

21 /* инициализация трех семафоров */

22 Semjnit(&shared.mutex, 0, 1);

23 Semjnit(&shared.nempty, 0, NBUFF);

24 Semjnit(&shared.nstored, 0, 0);

25 /* создание всех производителей и одного потребителя */

26 Set concurrency(nproducers + 1);

27 for (1 - 0: i < nproducers; i++) {

28 count[1] - 0:

29 Pthread create(&tid produce[1], NULL, produce, &count[i]);

30 }

31 Pthread create(&tid consume, NULL, consume, NULL);

32 /* ожидание завершения всех производителей и потребителя */

33 for (i - 0; i < nproducers; i++) {

34 PthreadJoin(tid produce[l], NULL):

35 printf( count[ d] = %й\п . i, count[1]);

36 }

37 Pthread join(tid consume, NULL):

38 Sem destroy(&shared.mutex);

39 Sem destroy(&shared.nempty):

40 Sem destroy(&shared.nstored);

41 exit(O):

42 }

Глобальные переменные

4 Глобальная переменная n i terns хранит число элементов, которые должны быть совместно произведены. Переменная nproducers хранит число потоков-производителей. Оба эти значения устанавливаются с помощью аргументов командной строки.

Общая структура

5-10 В структуру shared добавляются два новых элемента: nput, обозначающий индекс следующего элемента, куда должен быть помещен объект (по модулю BUFF), и nputval - следующее значение, которое будет помещено в буфер. Эти две переменные взяты из нащего рещения в листингах 7.1 и 7.2. Они нужны для синхронизации нескольких потоков-производителей,

Новые аргументы командной строки

17-20 Два новых аргумента командной строки указывают полное количество элементов, которые должны быть помещены в буфер, и количество потоков-производителей.



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.
Копирование материалов разрешено исключительно при условии цититирования.