Главная страница Взаимодействие нетривиальных процессов 5 pthread mutex t mutex: 6 long counter: 7 } shared = { 8 PTHREAD MUTEX INITIALIZER 9 }: 10 void *incr(void *): 11 int 12 mainCint argc. char **argv) 13 { 14 int i. nthreads: 15 pthread t tid[MAXNTHREADS]: 16 if (argc != 3) 17 err quit( usage: incr pxmutexl <#loops> <#threads> ): 18 nloop = atoi(argv[l]): 19 nthreads - min(atoi(argv[2]). MAXNTHREADS): 20 /* блокировка взаимного исключения */ 21 Pthread mutexJock(&shared.mutex): 22 /* создание потоков */ 23 Set concurrency(nthreads): 24 for (i = 0: i < nthreads: i++) { 25 Pthread create(&tid[i]. NULL. incr. NULL): 26 } 27 /* запуск таймера и разблокирование взаимного исключения */ 28 Start time(); 29 Pthread mutex unlock(&shared.mutex): 30 /* ожидание завершения работы потоков */ 31 for (i = 0: i < nthreads: i++) { 32 PthreadJoin(tid[i]. NULL): 33 } 34 printf( microseconds: X.Of usec\n . Stop time()): 35 if (shared.counter != nloop * nthreads) 36 printf( error: counter = Xld\n . shared.counter); 37 exit(O): 38 } Общие данные 4-9 Совместно используемые потоками данные состоят из взаимного исключения и счетчика. Взаимное исключение инициализируется статически. Блокирование взаимного исключения и создание потоков 20-26 Основной поток блокирует взаимное исключение перед созданием прочих потоков, чтобы ни один из них не получил это исключение до тех пор, пока все они не будут созданы. Вызывается функция setconcurrency, создаются потоки. Каждый поток выполняет функцию incr, текст которой будет приведен позже. Запуск таймера и разблокирование взаимного исключения 27-36 После создания всех потоков главный поток запускает таймер и освобождает взаимное исключение. Затем он ожидает завершения всех потоков, после чего останавливает таймер и выводит полное время работы. В листинге А.20 приведен текст функции i пег, выполняемой каждым из потоков. Листинг А.20. Функция incr, выполняемая потоками / /bench / i ncr pxmutexl. с 39 void * 40 incrCvoid *arg) 41 { 42 int i; 43 for (i - 0; i < nloop; i++) { 44 Pthread mutexJockC&shared.mutex): 45 shared.counter++: 46 Pthread mutex unlock(&shared.mutex); 47 } 48 return(NULL); 49 } Увеличение счетчика - критическая область кода 44-46 Операция увеличения счетчика осуществляется после получения блокировки на взаимное исключение. После этого взаимное исключение разблокируется. Блокировки чтения-записи Программа, использующая блокировки чтения-записи, является слегка измененной версией программы с взаимными исключениями Posix. Поток должен установить блокировку файла, прежде чем увеличивать общий счетчик. ПРИМЕЧАНИЕ - Существует не так уж много систем, в которых реализованы блокировки чтения-записи, являющиеся частью стандарта Unix 98 и разрабатываемые рабочей группой Posix.Ij. Измерения в этом разделе проводились в системе Solaris 2.6 с использованием блокировок, описанных в документации на странице rwlock(3T). Эта реализация обеспечивает тот же набор функций, что и предлагаемые блокировки чтения-записи Posix. Для использования этих функций мы применяем тривиальные функции-обертки. В Digital Unix 4.0В мы использовали блокировки чтения-записи поточно-независимых служб, описанные на странице документации tis rwlock. Мы не приводим листингов с несущественными изменениями, необходимыми для использования этих блокировок. В листинге А.21 приведен текст функции mai п, а в листинге А.22 - текст функции incr. Листинг А.21. Функция main для блокировок чтения-записи bench/i ncr rwlоск1.с 1 #include unpipc.h 2 #include <synch.h> /* Заголовочный файл для Solaris */ 3 void Rw wrlock(rwlock t *rwptr): 4 void Rw unlock(rwlock t *rwptr): 5 #define MAXNTHREADS 100 6 int nloop: 7 struct { 8 rwlock t rwlock; /* тип данных Solaris */ 9 long counter: 10 } shared; /* инициализация 0 -> USYNCJHREAD */ 11 void *incr(void *); 12 int 13 mainCint argc. char **argv) 14 { 15 int i. nthreads: 16 pthread t tid[MAXNTHREADS]: 17 if (argc != 3) 18 err quit( usage: incr rwlockl <#loops> <#threads> ); 19 nloop = atoi(argv[l]): 20 nthreads - min(atoi(argv[2]). MAXNTHREADS); 21 /* получение блокировки на запись */ 22 Rw wrlock(&shared.rwlock); 23 /* создание всех потоков */ 24 Set concurrency(nthreads): 25 for (i = 0: i < nthreads; i++) { 26 Pthread create(&tid[i], NULL, incr, NULL); 27 } 28 /* запуск таймера и снятие блокировки */ 29 Start time(): 30 Rw unlock(&shared.rwlock); 31 /* ожидание завершения всех потоков */ 32 for (i = 0: i < nthreads; i++) { 33 PthreadJoin(tid[i]. NULL); 34 } 35 printf( microseconds; .Of usec\n . Stop time()): 36 if (shared.counter 1= nloop * nthreads) 37 printf( error: counter = ld\n . shared.counter): 38 exit(O): 39 } Листинг A.22. Увеличение общего счетчика с использованием блокировок чтения-записи bench/i ПС r rwlоск1.с 40 void * 41 incr(void *arg) 42 { 43 int i: 44 for (i = 0: i < nloop; i++) { продолжение
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |