Главная страница Взаимодействие нетривиальных процессов 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 Два новых аргумента командной строки указывают полное количество элементов, которые должны быть помещены в буфер, и количество потоков-производителей.
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |