Книга: Программирование для Linux. Профессиональный подход
Листинг 4.11. (job-queue2.c) Работа с очередью заданий, защищенной исключающим семафором
Листинг 4.11. (job-queue2.c) Работа с очередью заданий, защищенной исключающим семафором
#include <malloc.h>
#include <pthread.h>
struct job {
/* Ссылка на следующий элемент связанного списка. */
struct job* next;
/* Другие поля, описывающие требуемую операцию... */
};
/* Список отложенных заданий. */
struct job* job_queue;
/* Исключающий семафор, защищающий очередь. */
pthread_mutex_t job_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Обработка заданий до тех пор, пока очередь не опустеет. */
void* thread_function(void* arg) {
while (1) {
struct job* next_job;
/* Захват семафора, защищающего очередь. */
pthread_mutex_lock(&job_queue_mutex);
/* Теперь можно проверить, является ли очередь пустой. */
if (job_queue == NULL)
next_job = NULL;
else {
/* Запрашиваем следующее задание. */
next_job = job_queue;
/* Удаляем задание из списка. */
job_queue = job_queue->next;
}
/* Освобождаем семафор, так как работа с очередью окончена. */
pthread_mutex_unlock(&job_queue_mutex);
/* Если очередь пуста, завершаем поток. */
if (next_job == NULL)
break;
/* Выполняем задание. */
process_job(next_job);
/* Очистка. */
free(next_job);
}
return NULL;
}
Все операции доступа к совместно используемому указателю job_queue
происходят между вызовами функций pthread_mutex_lock()
и pthread_mutex_unlock()
. Объект задания, ссылка на который хранится в переменной next_job
, обрабатывается только после того, как ссылка на него удаляется из очереди, что позволяет обезопасить этот объект от других потоков.
Обратите внимание на то, что, если очередь пуста (т.е. указатель job_queue
равен NULL
), цикл не завершается немедленно. Это привело бы к тому, что исключающий семафор так и остался бы в захваченном состоянии и не позволил бы ни одному другому потоку получить доступ к очереди заданий. Мы действуем иначе: записываем в переменную next_job
значение NULL
и выходим из цикла только после освобождения семафора.
Исключающий семафор блокирует доступ к участку программы, а не к переменной. В обязанности программиста входит написать код для захвата семафора перед доступом к переменной и последующего его освобождения. Вот как. например, может выглядеть функция, добавляющая новое задание к очереди:
void enqueue_job(struct job* new_job) {
pthread_mutex_lock(&job_queue_mutex);
new_job->next = job_queue;
job_queue = new_job;
pthread_mutex_unlock(&job_queue_mutex);
}
- Листинг 10.1. (simpleid.c) Отображение идентификаторов пользователя и группы
- Практическая работа 53. Запуск Access. Работа с объектами базы данных
- Лекция 15. Работа с базами данных
- Работа с ресурсами локальной сети
- Эффективная работа с временными файлами сортировки
- Ускоренная работа с индексами
- HR-брендинг: Работа с поколением Y, новые инструменты для коммуникации, развитие корпоративной культуры и еще 9 эффектив...
- Безопасная работа с внешними таблицами
- Работа со строками
- Модули констукторов заданий
- 9.2. Работа прокси-сервера
- 3. Заработок для фотографов: заработать на фото – сайты фотобанков