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

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

Жанры

Программирование для 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

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

Боярышня Дуняша 2

Меллер Юлия Викторовна
2. Боярышня
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Боярышня Дуняша 2

Низший - Инфериор. Компиляция. Книги 1-19

Михайлов Дем Алексеевич
Фантастика 2023. Компиляция
Фантастика:
боевая фантастика
5.00
рейтинг книги
Низший - Инфериор. Компиляция. Книги 1-19

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

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

Возлюби болезнь свою

Синельников Валерий Владимирович
Научно-образовательная:
психология
7.71
рейтинг книги
Возлюби болезнь свою

Чехов. Книга 2

Гоблин (MeXXanik)
2. Адвокат Чехов
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Чехов. Книга 2

Вперед в прошлое 3

Ратманов Денис
3. Вперёд в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 3

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

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

Товарищ "Чума" 10

lanpirot
10. Товарищ "Чума"
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Товарищ Чума 10

Реванш

СветочкаN
Фантастика:
фэнтези
5.00
рейтинг книги
Реванш

Родословная. Том 4

Ткачев Андрей Юрьевич
4. Линия крови
Фантастика:
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Родословная. Том 4

Черный Маг Императора 4

Герда Александр
4. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 4

Товарищ «Чума» 8

lanpirot
8. Товарищ "Чума"
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Товарищ «Чума» 8

Романов. Том 1 и Том 2

Кощеев Владимир
1. Романов
Фантастика:
фэнтези
попаданцы
альтернативная история
5.25
рейтинг книги
Романов. Том 1 и Том 2

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

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