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

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

Жанры

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

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

Шрифт:

Чаще всего взаимоблокировка возникает, когда группа потоков пытается захватить один и тот же набор объектов. Рассмотрим, к примеру, программу, в которой два потока, выполняющих разные потоковые функции, должны захватить одни и те же два исключающих семафора. Предположим, ноток А захватывает сначала семафор 1, а затем семафор 2, в то время как поток Б захватывает семафоры в обратном порядке. Возможна достаточно неприятная ситуация, когда после захвата семафора 1 потоком А операционная система активизирует поток Б, который захватит поток 2. Далее оба потока окажутся заблокированными, так как им будет закрыт доступ к семафорам

друг друга.

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

4.5. Реализация потоков в Linux

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

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

Сказанное иллюстрирует программа

thread-pid
, показанная в листинге 4.15. Она отображает идентификатор главного потока с помощью функции
getpid
и создает новый поток, в котором тоже выводится значение идентификатора, после чего оба потока входят в бесконечный цикл.

Листинг 4.15. (thread-pid.c) Вывод идентификаторов потоков

#include <pthread.h>

#include <stdio.h>

#include <unistd.h>

void* thread_function(void* arg) {

 fprintf(stderr, "child thread pid is %d\n", (int) getpid);

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

 while (1);

 return NULL;

}

int main {

 pthread_t thread;

 fprintf(stderr, "main thread pid is %d\n", (int)getpid);

 pthread_create(&thread, NULL, &thread_function, NULL);

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

 while (1);

 return 0;

}

Запустите программу в фоновом режиме, а затем вызовите команду

ps x
, чтобы увидеть список выполняющихся процессов. Не забудьте затем уничтожить программу
thread-pid
, так как она потребляет ресурсы процессора. Вот что мы получим:

% cc thread-pid.c -о thread-pid -lpthread

% ./thread-pid &

[1] 14608

main thread pid is 14608

child thread pid is 14610

% ps x

PID TTY STAT TIME COMMAND

14042 pts/9 S 0:00 bash

14068 pts/9 R 0:01 ./thread-pid

14069 pts/9 S 0:00 ./thread-pid

14610 pts/9 R 0:01 ./thread-pid

14611 pts/9 R 0:00 ps x

% kill 14608

[1]+ Terminated ./thread-pid

Сообщения
интерпретатора команд» касающиеся управления заданиями

Строки, начинающиеся с записи

[1]
, поступают от интерпретатора команд. Если программа запускается в фоновом режиме, интерпретатор назначает ей номер задания — в данном случае 1 — и сообщает ее идентификатор. Когда фоновое задание завершается, интерпретатор сообщает об этом при вызове первой же команды

Обратите внимание на то, что программе

thread-pid
соответствуют три процесса. Первый из них, с идентификатором 14608, — это основной поток программы. Третий, с идентификатором 14610, — это дочерний поток, выполняющий функцию
thread_function
. Что же такое тогда второй поток, с идентификатором 14609? Это "управляющий поток", являющийся частью внутреннего механизма реализации потоков в Linux. Он создается, когда программа вызывает функцию
pthread_create
.

4.5.1. Обработка сигналов

Предположим, что многопотоковая программа принимает сигнал. В каком потоке будет вызван обработчик сигнала? Это зависит от версии UNIX. В Linux поведение программы объясняется тем. что потоки на самом деле реализуются в виде процессов.

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

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

Тем не менее подобная особенность реализации библиотеки Pthreads в Linux не согласуется со стандартом POSIX. Нельзя полагаться на нее в программах, рассчитанных на то, чтобы быть переносимыми.

В многопотоковой программе один поток может послать сигнал другому. Для этого предназначена функция

pthread_kill
. Ее первым параметром является идентификатор потока, а второй параметр — это номер сигнала.

4.5.2. Системный вызов clone

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

Чай и водка в истории России

Похлебкин Вильям Васильевич
Дом и Семья:
кулинария
6.25
рейтинг книги
Чай и водка в истории России

Старый тракт (сборник)

Марков Георгий Мокеевич
Сибириада
Проза:
современная проза
7.12
рейтинг книги
Старый тракт (сборник)

Александр Агренев. Трилогия

Кулаков Алексей Иванович
Александр Агренев
Фантастика:
альтернативная история
9.17
рейтинг книги
Александр Агренев. Трилогия

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

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

Газлайтер. Том 6

Володин Григорий Григорьевич
6. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 6

После Кастанеды: дальнейшее исследование

Ксендзюк Алексей Петрович
Религия и эзотерика:
эзотерика
5.00
рейтинг книги
После Кастанеды: дальнейшее исследование

Чёрная вдова

Безуглов Анатолий Алексеевич
5.00
рейтинг книги
Чёрная вдова

Антракт. Поминки. Жизнеописание. Шатало

Эдлис Юлиу
5.00
рейтинг книги
Антракт. Поминки. Жизнеописание. Шатало

Годы странствий

Чулков Георгий Иванович
Документальная литература:
биографии и мемуары
6.25
рейтинг книги
Годы странствий

Блокадная книга

Гранин Даниил Александрович
Научно-образовательная:
история
8.81
рейтинг книги
Блокадная книга

Неучтенный элемент. Том 3

NikL
3. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 3

Золотая лихорадка

Задорнов Николай Павлович
2. Освоение Сибири и Дальнего Востока
Проза:
историческая проза
7.29
рейтинг книги
Золотая лихорадка

В поисках христианской свободы

Френц Реймонд
Религия и эзотерика:
прочая религиозная литература
5.00
рейтинг книги
В поисках христианской свободы

Технологии программирования

Камаев В А
Компьютеры и Интернет:
прочая компьютерная литература
5.00
рейтинг книги
Технологии программирования