Главная страница Взаимодействие нетривиальных процессов 3 int nloop: 4 struct { 5 int semid; 6 long counter; 7 } shared; 8 struct sembuf postop, waitop; 9 void *incr(void *): 10 int 11 mainCint argc. char **argv) 12 { 13 int i. nthreads; 14 pthread t tid[MAXNTHREADS]; 15 union semun arg; 16 if (argc != 3) 17 err quit( usage: incr svseml <#loops> <#threads>); 18 nloop = atoi(argv[l]); 19 nthreads = min(atoi(argv[2]), MAXNTHREADS): 20 /* создание семафора и инициализация его значением О */ 21 shared.semid = Seniget(IPC PRIVATE, 1, IPCJREAT SVSEM MODE); 22 arg.val = 0; 23 Semctl(shared.semid. 0. SETVAL, arg): 24 postop.sem num = 0: /* инициализация двух структур semop */ 25 postop.sem op = 1 26 postop.seffl flg = 0 27 waitop.sem num = 0 28 waitop.seffl op = -1; 29 waitop.sem flg = 0: 30 /* создание всех потоков */ 31 Set concurrency(nthreads): 32 for (i = 0; i < nthreads; i++) { 33 Pthread create(&tid[i]. NULL. incr. NULL); 34 } 35 /* запуск таймера и разблокирование семафора */ 36 Start time(): 37 Semop(shared.semid. &postop, 1); /* up by 1 */ 38 /* ожидание завершения всех потоков */ 39 for (i = 0; i < nthreads; i++) { 40 PthreadJoin(tid[i], NULL); 41 } 42 printf( microseconds: .Of usec\n . Stop time()); 43 if (shared.counter != nloop * nthreads) 44 printf ( error: counter ld\n , shared, counter): 45 Semctl (shared, semid. 0. IPCJMID); 46 exit(O); 47 } Листинг А.28. Увеличение общего счетчика с использованием семафоров System V bench/incr svseml.c 48 void * 49 incrCvoid *arg) 50 { 51 int i; 52 for (i = 0: i < nloop; i++) { 53 SemopCshared.semid, &waitop. 1); 54 shared.counter++; 55 SemopCshared.semid. &postop. 1); 56 } 57 return(NULL): 58 } 20-23 Создается семафор с одним элементом, значение которого инициализируется нулем. 24-29 Инициализируются две структуры semop: одна для увеличения семафора, а другая для ожидания его изменения. Обратите внимание, что поле semf 1 g в обеих структурах имеет значение 0: флаг SEM UNDO не установлен. Семафоры System V с флагом SEM UNDO Единственное отличие от программы из листинга А.27 заключается в том, что поле sem flg структур semop устанавливается равным SEM UNDO, а не 0. Мы не приводим в книге новый листинг с этим небольшим изменением. Блокировка записей fcntl Последняя программа использует fcntl для синхронизации. Функция main приведена в листинге А.ЗО. Эта программа будет выполняться успешно только в том случае, если количество потоков равно 1, поскольку блокировка fcntl предназначена для использования между процессами, а не между потоками одного процесса. При указании нескольких потоков каждый из них всегда имеет возможность получить блокировку (то есть вызовы writew lock не приводят к остановке потока, потому что процесс уже является владельцем блокировки), и конечное значение счетчика оказывается неправильным. Функция i пег, использующая блокировку записей, приведена в листинге А.29. Листинг А.29. Увеличение общего счетчика с использованием блокировки записей fcntl bench/incr fcntll.c 44 void * 45 incrCvoid *arg) 46 { 47 int i; 48 for (i = 0; i < nloop; i++) { 49 WritewJockCshared.fd, 0. SEEKJET, 0); 50 shared.counter++; 51 UnJock(shared.fd, 0, SEEKJET. 0): 52 } 53 return(NULL): 54 } Листинг А.ЗО. Функция main для измерения производительности блокировки fcntl bench/incr fcntll.c 4 #include unpipc.h 5 #define MAXNTHREADS 100 6 int nloop: 7 struct { 8 int fd; 9 long counter; 10 } shared; 11 void *incr(void *); 12 int 13 mainCint argc. char **argv) 14 { 15 int i. nthreads: 16 char *pathname; 17 pthread t tid[MAXNTHREADS]: 18 if (argc != 4) 19 err quit( usage: incr fcntll <pathname> <#loops> <#threads> ): 20 pathname = argv[l]; 21 nloop = atoi(argv[2]); 22 nthreads = min(atoi(argv[3]). MAXNTHREADS); 23 /* создание файла и получение блокировки на запись */ 24 shared.fd = Open (pathname, 0 RDWR OJREAT OJRUNC. FILE MODE); 25 WritewJock(shared.fd. 0. SEEKJET. 0); 26 /* создание всех потоков */ 27 Set concurrency(nthreads); 28 for (i = 0: i < nthreads; i++) { 29 Pthread create(&tid[i]. NULL. incr. NULL): 30 } 31 /* запуск таймера и снятие блокировки на запись */ 32 StartJimeO; 33 UnJоск(shared.fd. 0. SEEKJET, 0): 34 /* ожидание завершения всех потоков */ 35 for (i = 0: i < nthreads; i++) { 36 PthreadJoin(tid[i], NULL); 37 } 38 pri ntf ( microseconds: .Of usec\n , StopJimeO); 39 if (shared.counter != nloop * nthreads) 40 printf( error: counter = Xld\n . shared,counter); 41 Unl ink(pathname); 42 exit(O); 43 }
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |