Как было отмечено ранее, потоку может быть необходимо ждать какого-нибудь события. Наиболее очевидный выбор из представленного выше списка функций — это функция
volatile int data_ready = 0;
consumer() {
while (1) {
while (!data_ready) {
// wait
}
// Обработать данные
}
}
«Потребитель» вечно находится в своем главном обрабатывающем цикле (while(1)
Здесь мы можем столкнуться с новой проблемой. Как «потребителю» сбрасывать флаг
consumer() {
while (1) {
pthread_sleepon_lock();
while (!data_ready) {
// WAIT
}
// Обработать данные
data_ready = 0;
pthread_sleepon_unlock();
}
}
Здесь мы добавили «потребителю» установку и снятие блокировки. Это означает, что потребитель может теперь
Великолепно! А как насчет собственно процесса ожидания? Как мы и предполагали ранее, там действительно применяется вызов функции
while (!data_ready) {
pthread_sleepon_wait(&data_ready);
}
Функция
1. Разблокирует мутекс библиотеки ждущих блокировок.
2. Выполняет собственно операцию ожидания.
3. Снова блокирует мутекс библиотеки ждущих блокировок.
Причина обязательной разблокировки/блокировки мутекса библиотеки проста: поскольку суть мутекса состоит в обеспечении взаимного исключения доступа к флагу
Давайте перейдем теперь к потоку-«производителю» и рассмотрим, как он использует библиотеку ждущих блокировок. Вот его полная реализация:
producer() {
while (1) {
// Ждать прерывания от оборудования...
pthread_sleepon_lock();
data_ready = 1;
pthread_sleepon_signal(&data_ready);
pthread_sleepon_unlock();
}
}
Как вы видите, поток-«производитель» также блокирует мутекс, чтобы получить монопольный доступ к флагу
Давайте рассмотрим происходящее в подробностях. Определим состояния «потребителя» и «производителя» следующим образом:
Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT