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

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

Жанры

Программирование для Linux. Профессиональный подход

Самьюэл Алекс

Шрифт:

Похожая функция

pthread_cond_broadcast
разблокирует все потоки, ожидающие данного сигнала.

■ Функция

pthread_cond_wait
блокирует вызывающий ее поток до тех пор, пока не будет получен сигнал об изменении заданной переменной. Первым ее аргументом является указатель на объект типа
pthread_cond_t
. Второй аргумент — это указатель на объект исключающего семафора (тип
pthread_mutex_t
).

В момент вызова функции

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

Перечисленные ниже этапы должны выполняться всякий раз, когда программа тем или иным способом меняет результат проверки условия, контролируемого сигнальной переменной (в нашей программе условие — это значение флага):

1. Захватить исключающий семафор, дополняющий сигнальную переменную.

2. Выполнить действие, включающее изменение результата проверки условия (в нашем случае — установить флаг).

3. Послать сигнал (возможно, широковещательный) об изменении условия.

4. Освободить исключающий семафор.

В листинге 4.14 показана измененная версия предыдущего примера, в которой на этот раз флаг защищается сигнальной переменной. Обратите внимание на то, что в функции

thread_function
исключающий семафор захватывается до того, как будет проверено значение переменной
thread_flag
. Захват автоматически снимается функцией
pthread_cond_wait
перед тем, как поток оказывается заблокированным, и также автоматически восстанавливается по завершении функции:

Листинг 4.14. (condvar.c) Управление работой потока с помощью сигнальной переменной

#include <pthread.h>

int thread_flag;

pthread_cond_t thread_flag_cv;

pthread_mutex_t thread_flag_mutex;

void initialize_flag {

 /* Инициализация исключающего семафора и сигнальной

переменной. */

 pthread_mutex_init(&thread_flag_mutex, NULL);

 pthread_cond_init(&thread_flag_cv, NULL);

 /* Инициализация флага. */

 thread_flag = 0;

}

/* Если флаг установлен, многократно вызывается функция

do_work. В противном случае поток блокируется. */

void* thread_function(void* thread_arg) {

 /* Бесконечный цикл. */

 while (1) {

/* Захватываем исключающий семафор, прежде чем обращаться

к флагу. */

pthread_mutex_lock(&thread_flag_mutex);

while (!thread_flag)

/* Флаг сброшен. Ожидаем сигнала об изменении условной

переменной, указывающего на то, что флаг установлен.

При поступлении сигнала поток разблокируется и снова

проверяет флаг. */

pthread_cond_wait(&thread_flag_cv, &thread_flag_mutex);

/* При выходе из цикла освобождаем исключающий семафор. */

pthread_mutex_unlock(&thread_flag_mutex);

/* Выполняем требуемые действия. */

do_work;

 }

 return NULL;

}

/* Задаем значение флага равным FLAG_VALUE. */

void set_thread_flag(int flag_value) {

 /* Захватываем исключающий семафор, прежде чем изменять

значение флага. */

 pthread_mutex_lock(&thread_flag_mutex);

 /* Устанавливаем флаг и посылаем сигнал функции

thread_function, заблокированной в ожидании флага.

Правда, функция не сможет проверить флаг, пока

исключающий семафор не будет освобожден. */

 thread_flag = flag_value;

 pthread_cond_signal(&thread_flag_cv);

 /* освобождаем исключающий семафор. */

 pthread_mutex_unlock(&thread_flag_mutex);

}

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

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

pthread_cond_broadcast
можно разблокировать произвольное число потоков.

4.4.7. Взаимоблокировки двух и более потоков

Взаимоблокировка происходит, когда два (или более) потока блокируются в ожидании события, наступление которого на самом деле зависит от действий одного из заблокированных потоков. Например, если поток A ожидает изменения сигнальной переменной, устанавливаемой в потоке Б, а поток Б, в свою очередь, ждет сигнала от потока А, возникает тупиковая ситуация. Ни один из потоков никогда не пошлет сигнал другому. Необходимо тщательно избегать таких ситуаций, потому что их очень трудно обнаруживать.

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

Отмороженный

Гарцевич Евгений Александрович
1. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный

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

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

Кодекс Крови. Книга ХI

Борзых М.
11. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХI

Законы Рода. Том 4

Мельник Андрей
4. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 4

Лед тронулся, тренер! Но что делать со стояком? Том 2

Некрасов Игорь
2. Ледовая Корона
Любовные романы:
эро литература
5.00
рейтинг книги
Лед тронулся, тренер! Но что делать со стояком? Том 2

Гнев Пламенных

Дмитриева Ольга Олеговна
5. Пламенная
Фантастика:
фэнтези
4.80
рейтинг книги
Гнев Пламенных

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

Винокуров Юрий
19. Кодекс Охотника
Фантастика:
фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XIX

Изгой Проклятого Клана. Том 3

Пламенев Владимир
3. Изгой
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Изгой Проклятого Клана. Том 3

Метатель. Книга 2

Тарасов Ник
2. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Метатель. Книга 2

Эммануэль

Арсан Эммануэль
1. Эммануэль
Любовные романы:
эро литература
7.38
рейтинг книги
Эммануэль

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

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

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

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

Кодекс Императора IV

Сапфир Олег
4. Кодекс Императора
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Императора IV

Имперец. Том 1 и Том 2

Романов Михаил Яковлевич
1. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Имперец. Том 1 и Том 2