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

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

Жанры

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

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

Шрифт:

В одном процессе у нас имеется несколько потоков-производителей и один поток-потребитель. Целочисленный массив buff содержит производимые и потребляемые данные (данные совместного пользования). Для простоты производители просто устанавливают значение buff[0] в 0, buff [1] в 1 и т.д. Потребитель перебирает элементы массива, проверяя правильность записей.

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

Рис. 7.1. Производители и потребитель

Листинг 7.1. [1] Функция main

//mutex/prodcons2.с

1 #include "unpipc.h"

2 #define MAXNITEMS 1000000

3 #define MAXNTHREADS 100

4 int nitems; /* только для чтения потребителем и производителем */

5 struct {

6 pthread_mutex_t mutex;

1

Все исходные тексты, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com/download.

7 int buff[MAXNITEMS];

8 int nput;

9 int nval;

10 } shared = {

11 PTHREAD_MUTEX_INITIALIZER

12 };

13 void *produce(void *), *consume(void *);

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: prodcons2 <#items> <#threads>");

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

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

23 Set_concurrency(nthreads);

24 /* запуск всех потоков-производителей */

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

26 count[i] = 0;

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

28 }

29 /* ожидание завершения всех производителей */

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

31 Pthread_join(tid_produce[i], NULL);

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

33 }

34 /* запуск и ожидание завершения потока-потребителя */

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

36 Pthread_join(tid_consume, NULL);

37 exit(0);

38 }

Совместное использование глобальных переменных потоками

4-12 Эти переменные совместно используются потоками. Мы объединяем их в структуру с именем shared вместе с взаимным исключением, чтобы подчеркнуть, что доступ к ним можно получить только вместе с ним. Переменная nput хранит индекс следующего элемента массива buff, подлежащего обработке, a nval содержит следующее значение, которое должно быть в него помещено (0, 1, 2 и т.д.). Мы выделяем память под эту структуру и инициализируем взаимное исключение, используемое для синхронизации потоков-производителей.

ПРИМЕЧАНИЕ

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

Аргументы командной строки

19-22 Первый аргумент командной строки указывает количество элементов, которые будут произведены производителями, а второй — количество запускаемых потоков-производителей.

Установка уровня параллельности

23 Функция set_concurrency (наша собственная) указывает подсистеме потоков количество одновременно выполняемых потоков. В Solaris 2.6 она просто вызывает thr_setconcurrency, причем ее запуск необходим, если мы хотим, чтобы у нескольких процессов-производителей была возможность начать выполняться. Если мы не сделаем этого вызова в системе Solaris, будет запущен только первый поток. В Digital Unix 4.0B наша функция set_concurrency не делает ничего, поскольку в этой системе по умолчанию все потоки процесса имеют равные права на вычислительные ресурсы.

ПРИМЕЧАНИЕ

Unix 98 требует наличия функции pthread_setconcurrency, выполняющей это же действие. Эта функция требуется для тех реализаций, которые мультиплексируют пользовательские потоки (создаваемые функцией pthread_create) на небольшое множество выполняемых потоков ядра. Такие реализации часто называются «многие-к-немногим» (many-to-few), «двухуровневые» (two-level) или «М-на-N» (M-to-N). В разделе 5.6 книги [3] отношения между пользовательскими потоками и потоками ядра рассматриваются более подробно.

Создание процессов-производителей

24-28 Создаются потоки-производители, каждый из которых вызывает функцию produce. Идентификаторы потоков хранятся в массиве tid_produce. Аргументом каждого потока-производителя является указатель на элемент массива count. Счетчики инициализируются значением 0, и каждый поток увеличивает значение своего счетчика на 1 при помещении очередного элемента в буфер. Содержимое массива счетчиков затем выводится на экран, так что мы можем узнать, сколько элементов было помещено в буфер каждым из потоков.

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

Бестужев. Служба Государевой Безопасности. Книга третья

Измайлов Сергей
3. Граф Бестужев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бестужев. Служба Государевой Безопасности. Книга третья

Группа крови на рукаве. Том 2

Вязовский Алексей
2. ГК
Фантастика:
боевая фантастика
альтернативная история
постапокалипсис
5.00
рейтинг книги
Группа крови на рукаве. Том 2

Я царь. Книга XXVIII

Дрейк Сириус
28. Дорогой барон!
Фантастика:
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Я царь. Книга XXVIII

Выйду замуж за спасателя

Рам Янка
1. Спасатели
Любовные романы:
современные любовные романы
7.00
рейтинг книги
Выйду замуж за спасателя

Серые сутки

Сай Ярослав
4. Медорфенов
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Серые сутки

Я не князь. Книга XIII

Дрейк Сириус
13. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я не князь. Книга XIII

Лебединая Дорога (сборник)

Семёнова Мария Васильевна
Приключения:
исторические приключения
9.04
рейтинг книги
Лебединая Дорога (сборник)

Некромант на страже человечества. Том 5

Клеванский Никита
5. Некромант на страже человечества
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Некромант на страже человечества. Том 5

Бастард Императора. Том 10

Орлов Андрей Юрьевич
10. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Бастард Императора. Том 10

Проданная Истинная. Месть по-драконьи

Белова Екатерина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Проданная Истинная. Месть по-драконьи

Я – Стрела. Трилогия

Суббота Светлана
Я - Стрела
Любовные романы:
любовно-фантастические романы
эро литература
6.82
рейтинг книги
Я – Стрела. Трилогия

Товарищ "Чума" 6

lanpirot
6. Товарищ "Чума"
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Товарищ Чума 6

Мастер 4

Чащин Валерий
4. Мастер
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Мастер 4

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

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