Чтение онлайн

на главную - закладки

Жанры

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:
Ожидание завершения работы производителей, запуск потребителя

29-36 Мы ожидаем завершения работы всех потоков-производителей, выводя содержимое счетчика для каждого потока, а затем запускаем единственный процесс-потребитель. Таким образом (на данный момент) мы исключаем необходимость синхронизации между потребителем и производителями. Мы ждем завершения работы потребителя, а затем завершаем работу процесса. В листинге 7.2 приведен текст функций produce и consume.

Листинг 7.2. Функции produce и consume

//mutex/prodcons2.с

39 void *

40 produce(void *arg)

41 {

42 for (;;) {

43 Pthread_mutex_lock(&shared.mutex);

44 if (shared.nput >= nitems) {

45 Pthread_mutex_unlock(&shared.mutex);

46 return(NULL); /* массив полный, готово */

47 }

48 shared.buff[shared.nput] = shared.nval;

49 shared.nput++;

50 shared.nval++;

51 Pthread_mutex_unlock(&shared.mutex);

52 *((int *) arg) += 1;

53 }

54 }

55 void *

56 consume(void *arg)

57 {

58 int i;

59 for (i = 0; i < nitems; i++) {

60 if (shared.buff[i] != i)

61 printf("buff[%d] = %d\n", i, shared.buff[i]);

62 }

63 return(NULL);

64 }

Формирование данных

42-53 Критическая область кода производителя состоит из проверки на достижение конца массива (завершение работы)

if (shared.nput >= nitems)

и трех строк, помещающих очередное значение в массив:

shared.buff[shared.nput] = shared.nval;

shared.nput++;

shared.nval++;

Мы защищаем эту область с помощью взаимного исключения, не забыв разблокировать его после завершения работы. Обратите внимание, что увеличение элемента count (через указатель arg) не относится к критической области, поскольку у каждого потока счетчик свой (массив count в функции main). Поэтому мы не включаем эту строку в блокируемую взаимным исключением область. Один из принципов хорошего стиля программирования заключается в минимизации объема кода, защищаемого взаимным исключением.

Потребитель проверяет содержимое массива

59-62 Потребитель проверяет правильность значений всех элементов массива и выводит сообщение в случае обнаружения ошибки. Как уже говорилось, эта функция запускается в единственном экземпляре и только после того, как все потоки-производители завершат свою работу, так что надобность в синхронизации отсутствует.

При запуске только что описанной программы с пятью процессами-производителями, которые должны вместе создать один миллион элементов данных, мы получим следующий результат:

solaris % prodcons2 1000000 5

count[0] = 167165

count[1] = 249891

count[2] = 194221

count[3] = 191815

count[4] = 196908

Как мы отмечали ранее, если убрать вызов set_concurrency, в системе Solaris 2.6 значение count[0] будет 1000000, а все остальные счетчики будут нулевыми.

Если убрать из этого примера блокировку с помощью взаимного исключения, он перестанет работать, как и предполагается. Потребитель обнаружит множество элементов buff[i], значения которых будут отличны от i. Также мы можем убедиться, что удаление блокировки ничего не изменит, если будет выполняться только один поток.

7.4. Блокировка и ожидание

Продемонстрируем теперь, что взаимные исключения предназначены для блокирования, но не для ожидания. Изменим наш пример из предыдущего раздела таким образом, чтобы потребитель запускался сразу же после запуска всех производителей. Это даст возможность потребителю обрабатывать данные по мере их формирования производителями в отличие от пpoгрaммы в листинге 7.1, в которой потребитель не запускался до тех пор, пока все производители не завершали свою работу. Теперь нам придется синхронизовать потребителя с производителями, чтобы первый обрабатывал только данные, уже сформированные последними.

В листинге 7.3 приведен текст функции main. Начало кода (до объявления функции main) не претерпело никаких изменений по сравнению с листингом 7.1.

Листинг 7.3. Функция main: запуск потребителя сразу после запуска производителей

//mutex/prodcons3.c

14 int

15 main(int argc, char **argv)

16 {

17 int i, nthreads, count[MAXNTHREADS];

18 pthread_t tid_produce[MAXNTHREADS], tid_consume;

19 if (argc != 3)

20 err_quit("usage: prodcons3 <#items> <#threads>");

21 nitems = min(atoi(argv[1]), MAXNITEMS);

22 nthreads = min(atoi(argv[2]), MAXNTHREADS);

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

24 Set_concurrency(nthreads + 1);

25 for (i = 0; i < nthreads; i++) {

26 count[i] = 0;

27 Pthread_create(&tid_produce[i], NULL, produce, &count[i]);

28 }

29 Pthread_create(&tid_consume, NULL, consume, NULL);

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

31 for (i = 0; i < nthreads; i++) {

32 Pthread_join(tid_produce[i], NULL);

33 printf("count[%d] = %d\n", i, count[i]);

34 }

35 Pthread_join(tid_consume, NULL);

36 exit(0);

37 }

Поделиться:
Популярные книги

На границе тучи ходят хмуро...

Кулаков Алексей Иванович
1. Александр Агренев
Фантастика:
альтернативная история
9.28
рейтинг книги
На границе тучи ходят хмуро...

Тринадцатый XII

NikL
12. Видящий смерть
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
7.00
рейтинг книги
Тринадцатый XII

Вернувшийся: Корпорация. Том III

Vector
3. Вернувшийся
Фантастика:
космическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Вернувшийся: Корпорация. Том III

Возвращение

Кораблев Родион
5. Другая сторона
Фантастика:
боевая фантастика
6.23
рейтинг книги
Возвращение

На границе империй. Том 9. Часть 5

INDIGO
18. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 5

Годы огневые

Кожевников Вадим Михайлович
Документальная литература:
биографии и мемуары
публицистика
5.00
рейтинг книги
Годы огневые

Моров. Том 1 и Том 2

Кощеев Владимир
1. Моров
Фантастика:
попаданцы
альтернативная история
аниме
5.25
рейтинг книги
Моров. Том 1 и Том 2

Скрытые чувства

Эльденберт Марина
Любовные романы:
любовно-фантастические романы
7.17
рейтинг книги
Скрытые чувства

Неучтенный элемент. Том 12

NikL
12. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 12

Герой

Бубела Олег Николаевич
4. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Герой

Эволюционер из трущоб. Том 8

Панарин Антон
8. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 8

Убивать чтобы жить 5

Бор Жорж
5. УЧЖ
Фантастика:
боевая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 5

Черный Маг Императора 13

Герда Александр
13. Черный маг императора
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 13

Хозяин Стужи

Петров Максим Николаевич
1. Злой Лед
Фантастика:
аниме
фэнтези
попаданцы
7.00
рейтинг книги
Хозяин Стужи