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

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

Жанры

Основы программирования в Linux
Шрифт:

pthread_mutex_t work_mutex; /* защищает work_area и time_to_exit */

#define WORK_SIZE 1024

char work_area[WORK_SIZE];

int time_to_exit = 0;

Далее инициализируется мьютекс:

res = pthread_mutex_init(&work_mutex, NULL);

if (res != 0) {

 perror("Mutex initialization failed");

 exit(EXIT_FAILURE);

}

Затем запускается новый

поток. Далее приведен код, выполняемый в функции потока:

pthread_mutex_lock(&work_mutex);

while(strncmp("end", work_area, 3) != 0) {

 printf("You input id characters\n", strlen(work_area)-1);

 work_area[0] = '\0';

 pthread_mutex_unlock(&work_mutex);

 sleep(1);

 pthread_mutex_lock(&work_mutex);

 while (work_area[0] == '\0') {

pthread_mutex_unlock(&work_mutex);

sleep(1);

pthread_mutex_lock(&work_mutex);

 }

}

time_to_exit = 1;

work_area[0] = '\0';

pthread_mutex_unlock(&work_mutex);

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

time_to_exit
, сотрите первый символ в рабочей области и завершите выполнение. 

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

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

Далее приведен поток

main
.

pthread_mutex_lock(&work_mutex)

printf("Input some text. Enter 'end' to finish\n");

while (!time_to_exit) {

 fgets(work_area, WORK_SIZE, stdin);

 pthread_mutex_unlock(&work_mutex);

 while(1) {

pthread_mutex_lock(&work_mutex);

if (work_area[0] != '\0') {

pthread_mutex_unlock(&work_mutex);

sleep(1);

} else {

break;

}

 }

}

pthread_mutex_unlock(&work_mutex);

Он аналогичен второму

потоку. Вы блокируете рабочую область и можете читать в нее текст, а затем вы снимаете блокировку, чтобы открыть доступ другому потоку для подсчета слов. Периодически вы блокируете мьютекс, проверяете, сосчитаны ли слова (элемент
work_area[0]
равен пустому символу), и освобождаете мьютекс, если нужно продолжить ожидание. Как уже отмечалось ранее, этот вид опроса и получения ответа в основном не слишком удачный прием и в реальной жизни вам, возможно, придется применить семафор для его замены. Тем не менее, программный код справляется с задачей демонстрации примера применения мьютекса.

Атрибуты потока

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

Во всех предыдущих примерах вы должны были повторно синхронизовать потоки с помощью функции

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

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

main
продолжает обслуживать пользователя. Когда создание копии закончено, второй поток может тут же завершиться. Ему не нужно присоединяться к потоку
main
.

Вы можете создать потоки, ведущие себя подобным образом. Они называются отсоединенными или обособленными потоками, и вы создаете их, изменяя атрибуты потока или вызывая функцию

pthread_detach
. Поскольку мы хотим продемонстрировать атрибуты, то применим здесь первый метод.

Самая важная функция, которая вам понадобится, —

pthread_attr_init
, инициализирующая объект атрибутов потока:

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);

И снова 0 возвращается в случае успешного завершения и код ошибки в случае аварийного.

Есть и функция для уничтожения:

pthread_attr_destroy
. Ее задача — обеспечить чистое уничтожение объекта атрибутов. После того как объект уничтожен, он не может быть использован снова до тех пор, пока не будет инициализирован повторно.

Когда вы инициализировали объект атрибутов потока, можно использовать множество дополнительных функций, с помощью которых задается поведение разных атрибутов. Далее перечислены основные из них (полный список вы можете найти в интерактивном справочном руководстве, в разделе, посвященном pthread.h), но мы рассмотрим подробно только два:

detechedstate
и
schedpolicy
.

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

Телохранитель Цесаревны

Зот Бакалавр
5. Герой Империи
Фантастика:
фэнтези
боевая фантастика
5.25
рейтинг книги
Телохранитель Цесаревны

Наследие Маозари 9

Панежин Евгений
9. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
сказочная фантастика
6.25
рейтинг книги
Наследие Маозари 9

Память

Буджолд Лоис Макмастер
10. Сага о Форкосиганах
Фантастика:
научная фантастика
9.41
рейтинг книги
Память

Эволюционер из трущоб. Том 10

Панарин Антон
10. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 10

Анти-Ксенонская Инициатива

Вайс Александр
7. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Анти-Ксенонская Инициатива

Мы друг друга не выбирали

Кистяева Марина
1. Мы выбираем...
Любовные романы:
остросюжетные любовные романы
прочие любовные романы
современные любовные романы
5.00
рейтинг книги
Мы друг друга не выбирали

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

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

Глэрд IX: Легионы во Тьме

Владимиров Денис
9. Глэрд
Фантастика:
боевая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Глэрд IX: Легионы во Тьме

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

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

Я Гордый часть 2

Машуков Тимур
2. Стальные яйца
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я Гордый часть 2

Мастер 8

Чащин Валерий
8. Мастер
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Мастер 8

Воин-Врач

Дмитриев Олег
1. Воин-Врач
Фантастика:
попаданцы
альтернативная история
историческое фэнтези
6.00
рейтинг книги
Воин-Врач

Войсковые разведчики в Афгане. Записки начальника разведки дивизии

Кузьмин Николай Павлович
1. Афган: Последняя война СССР
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Войсковые разведчики в Афгане. Записки начальника разведки дивизии

Неудержимый. Книга XXX

Боярский Андрей
30. Неудержимый
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Неудержимый. Книга XXX