4-9 Совместно используемые потоками данные состоят из взаимного исключения и счетчика. Взаимное исключение инициализируется статически.
Блокирование взаимного исключения и создание потоков
20-26 Основной поток блокирует взаимное исключение перед созданием прочих потоков, чтобы ни один из них не получил это исключение до тех пор, пока все они не будут созданы. Вызывается функция set_concurrency, создаются потоки. Каждый поток выполняет функцию incr, текст которой будет приведен позже.
Запуск таймера и разблокирование взаимного исключения
27-36 После создания всех потоков главный поток запускает таймер и освобождает взаимное исключение. Затем он ожидает завершения всех потоков, после чего останавливает таймер и выводит полное время работы. В листинге А.20 приведен текст функции incr, выполняемой каждым из потоков.
Листинг А.20. Функция incr, выполняемая потоками
//bench/incr_pxmutex1.c
39 void *
40 incr(void *arg)
41 {
42 int i;
43 for (i = 0; i < nloop; i++) {
44 Pthread_mutex_lock(&shared.mutex);
45 shared.counter++;
46 Pthread_mutex_unlock(&shared.mutex);
47 }
48 return(NULL);
49 }
Увеличение счетчика — критическая область кода
44-46 Операция увеличения счетчика осуществляется после получения блокировки на взаимное исключение. После этого взаимное исключение разблокируется.
Блокировки чтения-записи
Пpoгрaммa, использующая блокировки чтения-записи, является слегка измененной версией программы с взаимными исключениями Posix. Поток должен установить блокировку файла, прежде чем увеличивать общий счетчик.
ПРИМЕЧАНИЕ
Существует не так уж много систем, в которых реализованы блокировки чтения-записи, являющиеся частью стандарта Unix 98 и разрабатываемые рабочей группой Posix.1j. Измерения в этом разделе проводились в системе Solaris 2.6 с использованием блокировок, описанных в документации на странице rwlock(3T). Эта реализация обеспечивает тот же набор функций, что и предлагаемые блокировки чтения-записи Posix. Для использования этих функций мы применяем тривиальные функции-обертки.
В Digital Unix 4.0B
мы использовали блокировки чтения-записи поточно-независимых служб, описанные на странице документации tis_rwlock. Мы не приводим листингов с несущественными изменениями, необходимыми для использования этих блокировок.
В листинге А.21 приведен текст функции main, а в листинге А.22 — текст функции incr.
Листинг А.21. Функция main для блокировок чтения-записи
//bench/incr_rwlock1.c
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; /* инициализация О –> USYNC_THREAD */