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

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

Жанры

Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform

Кёртен Роб

Шрифт:

"Начало примера с производителем и потребителем...\n");

 // Создать поток-производитель и поток-потребитель

 pthread_create(NULL, NULL, producer, NULL);

 pthread_create(NULL, NULL, consumer, NULL);

 // Дать потокам немного повыполняться

 sleep(20);

}

Этот пример в значительной степени похож на программу с применением ждущей блокировки, с небольшими отличиями (мы добавили несколько вызовов printf,

а также функцию main, чтобы программа могла работать!) Первое отличие, которое бросается в глаза, — здесь использован новый тип данных,
pthread_cond_t
. Это просто декларация для условной переменной; мы назвали нашу условную переменную condvar.

Следующее, что видно из примера, — это то, что структура «потребителя» идентична таковой в предыдущем примере с ждущей блокировкой. Мы заменили функции pthread_sleepon_lock и pthread_sleepon_unlock на стандартные мутекс-ориентированные версии (pthread_mutex_lock и pthread_mutex_unlock). Функция pthread_sleepon_wait была заменена на функцию pthread_cond_wait.

Основное различие здесь состоит в том, что библиотека ждущих блокировок имеет скрытый внутренний мутекс, а при использовании условных переменных мутекс передается явно. Последний способ дает нам больше гибкости.

И, наконец, обратите внимание на то, что мы использовали функцию pthread_cond_signal вместо функции pthread_sleepon_signal (опять же, с явной передачей мутекса).

Функции phtread*_signal и pthread*_broadcast

В разделе о ждущих блокировках мы обещали обсудить различие между функциями pthread_sleepon_broadcast и pthread_sleepon_signal. Заодно поговорим и о различии между двумя аналогичными функциями, имеющими отношение к условным переменным: pthread_cond_signal и pthread_cond_broadcast.

В двух словах, функция в варианте «signal» разблокирует только один поток. Например, если бы несколько потоков находилось в ожидании по функции «wait», и некий поток вызвал бы функцию pthread*_signal, то был бы разблокирован только один из ждущих потоков. Который из них? Тот, у которого наивысший приоритет. Если имеется два или более потоков с одинаковым приоритетом, порядок «пробуждения» будет не определен. Применение же варианта pthread*_broadcast приведет к тому что будут разблокированы все ожидающие потоки.

Разблокировать все потоки может показаться излишним. Но с другой стороны, разблокировать только один (причем случайный поток тоже не совсем корректно.

Поэтому мы должны думать, где имеет смысл использовать какой вариант. Очевидно, что если у вас только один ждущий поток, как у нас и было во всех вариантах «потребителя», функция pthread*_signal прекрасно справится — будет разблокирован один поток, и как раз тот, который нужно (потому что других просто нет).

В ситуации с несколькими потоками в первую очередь следует выяснить: а почему

они ждут? Обычно на этот вопрос есть два ответа:

• все потоки рассматриваются как эквивалентные и реально образуют пул доступных потоков, готовых к обработке некоторого запроса;

• все потоки являются уникальными, и каждый из них ждет соблюдения своего специфического условия.

В первом случае мы можем представить себе, что код всех потоков имеет примерно следующий вид:

/*

 * cv1.c

*/

#include <stdio.h>

#include <pthread.h>

pthread_mutex_t mutex_data = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t cv_data = PTHREAD_COND_INITIALIZER;

int data;

thread1 {

 for (;;) {

pthread_mutex_lock(&mutex_data);

while (data == 0) {

pthread_cond_wait(&cv_data, &mutex_data);

}

// Сделать что-нибудь

pthread_mutex_unlock(&mutex_data);

 }

}

В этом случае абсолютно неважно, который именно из потоков получит данные — главное, чтобы хотя бы один сделал это и произвел над этими данными необходимые действия.

Однако, если ваш код подобен приведенному ниже, все будет несколько по-иному:

/*

 * cv2.c

*/

#include <stdio.h>

#include <pthread.h>

pthread_mutex_t mutex_xy = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t cv_xy = PTHREAD_COND_INITIALIZER;

int x, y;

int isprime(int);

thread1 {

 for (;;) {

pthread_mutex_lock(&mutex_xy);

while ((x > 7) && (y != 15)) {

pthread_cond_wait(&cv_xy, &mutex_xy);

}

// Сделать что-нибудь

pthread_mutex_unlock(&mutex_xy);

 }

}

thread2 {

 for (;;) {

pthread_mutex_lock(&mutex_xy);

while (!isprime(x)) {

pthread_cond_wait(&cv_xy, &mutex_xy);

}

// Сделать что-нибудь

pthread_mutex_unlock(&smutex_xy);

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

Сирота

Ланцов Михаил Алексеевич
1. Помещик
Фантастика:
альтернативная история
5.71
рейтинг книги
Сирота

Стеллар. Трибут

Прокофьев Роман Юрьевич
2. Стеллар
Фантастика:
боевая фантастика
рпг
8.75
рейтинг книги
Стеллар. Трибут

Смерть может танцевать 4

Вальтер Макс
4. Безликий
Фантастика:
боевая фантастика
5.85
рейтинг книги
Смерть может танцевать 4

Вечный. Книга IV

Рокотов Алексей
4. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга IV

СД. Том 17

Клеванский Кирилл Сергеевич
17. Сердце дракона
Фантастика:
боевая фантастика
6.70
рейтинг книги
СД. Том 17

Система Возвышения. Второй Том. Часть 1

Раздоров Николай
2. Система Возвышения
Фантастика:
фэнтези
7.92
рейтинг книги
Система Возвышения. Второй Том. Часть 1

Кодекс Охотника. Книга XV

Винокуров Юрий
15. Кодекс Охотника
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XV

Релокант. Вестник

Ascold Flow
2. Релокант в другой мир
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Релокант. Вестник

Горькие ягодки

Вайз Мариэлла
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Горькие ягодки

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

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

АН (цикл 11 книг)

Тарс Элиан
Аномальный наследник
Фантастика:
фэнтези
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
АН (цикл 11 книг)

Весь цикл «Десантник на престоле». Шесть книг

Ланцов Михаил Алексеевич
Десантник на престоле
Фантастика:
альтернативная история
8.38
рейтинг книги
Весь цикл «Десантник на престоле». Шесть книг

Рядовой. Назад в СССР. Книга 1

Гаусс Максим
1. Второй шанс
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Рядовой. Назад в СССР. Книга 1

Сколько стоит любовь

Завгородняя Анна Александровна
Любовные романы:
любовно-фантастические романы
6.22
рейтинг книги
Сколько стоит любовь