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

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

Жанры

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

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

Шрифт:

В Linux имеется функция

sem_getvalue
, позволяющая узнать текущее значение счетчика семафора. Это значение помещается в переменную типа
int
, на которую ссылается второй аргумент функции. Не пытайтесь на основании данного значения определять, стоит ли выполнять операцию ожидания или установки, так как это может привести к возникновению гонки: другой поток способен изменить счетчик семафора между вызовами функции
sem_getvalue
и какой-нибудь другой функции работы с семафором. Доверяйте только атомарным функциям
sem_wait
и
sem_post
.

Но

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

Листинг 4.12. (job-queue3.c) Работа с очередью заданий с применением семафора

#include <malloc.h>

#include <pthread.h>

#include <semaphore.h>

struct job {

 /* Ссылка на следующий элемент связанного списка. */

 struct job* next;

 /* Другие поля, описывающие требуемую операцию... */

};

/* Список отложенных заданий. */

struct job* job_queue;

/* Исключающий семафор, защищающий очередь. */

pthread_mutex_t job_queue_mutex =

 PTHREAD_MUTEX_INITIALIZER;

/* Семафор, подсчитывающий число гаданий в очереди. */

sem_t job_queue_count;

/* Начальная инициализация очереди. */

void initialize_job_queue {

 /* Вначале очередь пуста. */

 job_queue = NULL;

 /* Устанавливаем начальное значение счетчика семафора

равным 0. */

 sem_init(&job_queue_count, 0, 0);

}

/* Обработка заданий до тех пор, пока очередь не опустеет. */

void* thread_function(void* arg) {

 while (1) {

struct job* next_job;

/* Дожидаемся готовности семафора. Если его значение больше

нуля, значит, очередь не пуста; уменьшаем счетчик на 1.

В противном случае операция блокируется до тех пор, пока

в очереди не появится новое задание. */

sem_wait(&job_queue_count);

/* Захват исключающего семафора, защищающего очередь. */

pthread_mutex_lock(&job_queue_mutex);

/* Мы уже знаем, что
очередь не пуста, поэтому без лишней

проверки запрашиваем новое задание. */

next_job = job_queue;

/* Удаляем задание из списка. */

job_queue = job_queue->next;

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

очередью окончена. */

pthread_mutex_unlock(&job_queue_mutex);

/* Выполняем задание. */

process_job(next_job);

/* Очистка. */

free(next_job);

 }

 return NULL;

}

/* Добавление нового задания в начало очереди. */

void enqueue_job(/* Передача необходимых данных... */) {

 struct job* new_job;

 /* Выделение памяти для нового объекта задания. */

 new_job = (struct job*)malloc(sizeof(struct job));

 /* Заполнение остальных полей структуры JOB... */

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

к очереди. */

 pthread_mutex_lock(&job_queue_mutex);

 /* Помещаем новое задание в начало очереди. */

 new_job->next = job_queue;

 job_queue = new_job;

 /* Устанавливаем семафор, сообщая о том, что в очереди появилось

новое задание. Если есть потоки, заблокированные в ожидании

семафора, один из них будет разблокирован и

обработает задание. */

 sem_post(&job_queue_count);

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

 pthread_mutex_unlock(&job_queue_mutex);

}

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

Функция

enqueue_job
добавляет новое задание в очередь. Подобно потоковой функции, она захватывает исключающий семафор, перед тем как обратиться к очереди. После добавления задания функция
enqueue_job
устанавливает семафор, сообщая потокам о том, что задание доступно. В программе, показанной в листинге 4.12, потоки никогда не завершаются: если задания не поступают в течение длительного времени, все потоки переводятся в режим блокирования функцией
sem_wait
.

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

Усадьба леди Анны

Ром Полина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Усадьба леди Анны

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь

Светлая тьма. Советник

Шмаков Алексей Семенович
6. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Светлая тьма. Советник

Двойник Короля

Скабер Артемий
1. Двойник Короля
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Двойник Короля

Его нежеланная истинная

Кушкина Милена
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Его нежеланная истинная

Последний Паладин. Том 2

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

Измена. Наследник для дракона

Солт Елена
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Измена. Наследник для дракона

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Мастер темных Арканов

Карелин Сергей Витальевич
1. Мастер темных арканов
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Мастер темных Арканов

Адвокат империи

Карелин Сергей Витальевич
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Адвокат империи

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

Винокуров Юрий
21. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XXI

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

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

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

Flow Ascold
3. Граф Берестьев
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 3

Наследник

Шимохин Дмитрий
1. Старицкий
Приключения:
исторические приключения
5.00
рейтинг книги
Наследник