Создание нитей
Создание нитей отличается от создания процессов тем, что между нитями не существует "родственных" отношений (предок-потомок).
Все нити, за исключением главной нити, автоматически создаваемой при создании процесса, находятся на одном и том же уровне иерархии. Для нити не ведется список порожденных нитей; кроме того, нить не знает, какая нить ее породила.
При создании нити необходимо указать процедуру точки входа и аргумент. Каждой нити соответствует процедура точки входа с одним аргументом. Несколько нитей могут работать с одной и той же процедурой точки входа.
Нити соответствует набор атрибутов, которые определяют ее характеристики. Для установки атрибутов перед созданием нити необходимо определить объект атрибутов нити.
Объект атрибутов нити
Атрибуты нити хранятся в объекте со скрытой реализацией - объекте атрибутов нити, который используется при создании нити. Этот объект хранит набор атрибутов, зависящий от реализации опций POSIX. Обращение к объекту осуществляется с помощью переменной типа pthread_attr_t. В AIX тип данных pthread_attr_t обозначает указатель; в других системах это может быть структура или другой тип данных.
Создание и удаление объектов атрибутов нити
o
Объект атрибутов нити инициализируется значениями по умолчанию с помощью процедуры pthread_attr_init. Для работы с атрибутами предназначены специальные функции. Объект атрибутов нити удаляется с помощью функции pthread_attr_destroy. В зависимости от реализации библиотеки нитей, эта функция может освобождать память, динамически захваченную функцией pthread_attr_init.
В приведенном ниже примере объект атрибутов нити создается и инициализируется со значениями по умолчанию, затем используется при создании нити и удаляется:
pthread_attr_t attributes;
/* создается объект атрибутов */
...
if (!pthread_attr_init(&attributes)) {
/* объект атрибутов инициализируется */
...
/* работа с объектом атрибутов */
...
pthread_attr_destroy(&attributes);
/* удаление объекта атрибутов */
}Один объект атрибутов может применяться для создания нескольких нитей. Между вызовами операции создания нитей атрибуты объекта можно изменить. После создания нитей объект атрибутов можно удалить - эта операция не повлияет на работу созданных нитей.
Атрибут detachstate
Следующий атрибут определен всегда:
- Detachstate
- Определяет состояние запуска нити.
Значение атрибута можно считать процедурой pthread_attr_getdetachstate и установить процедурой pthread_attr_setdetachstate. Атрибут может принимать значение одной из следующих констант:
- PTHREAD_CREATE_DETACHED
- Указывает, что будет создана автономная нить
- PTHREAD_CREATE_JOINABLE
- Указывает, что будет создана подключаемая нить
Значение по умолчанию - PTHREAD_CREATE_JOINABLE.
Если была создана подключаемая нить, для нее необходимо вызвать функцию pthread_join. В противном случае в системе может оказаться недостаточно памяти для создания новой нити, так как каждая нить занимает относительно большой объем. Более подробная информация о функции pthread_join приведена в разделе Вызов функции pthread_join.
Прочие атрибуты нитей
В AIX дополнительно определены некоторые атрибуты, предназначенные для более точного управления нитями. Для их применения могут потребоваться специальные права доступа. Большинство программ правильно работают в том случае, если этим атрибутам присвоены значения по умолчанию. Применение перечисленных ниже атрибутов описано в разделе Работа с атрибутом inheritsched.
- Область действия
- Задает область действия нити
- Inheritsched
- Задает параметры наследования атрибутов планировщика нитей
- Schedparam
- Задает параметры планировщика для нити
- Schedpolicy
- Задает стратегию планирования для нити
Применение перечисленных ниже атрибутов стека описано в разделе Атрибуты стека.
- Stacksize
- Задает размер стека нити
- Stackaddr
- Задает адрес стека нити
- Guardsize
- Задает размер контрольной области стека нити
Создание нити с помощью функции pthread_create
Для создания нити предназначена функция pthread_create. Эта функция создает новую нить и запускает ее.
Применение объекта атрибутов нити
В вызове процедуры pthread_create можно указать объект атрибутов нити. Если задан указатель NULL, нить создается со значением атрибутов по умолчанию. Следовательно, следующий фрагмент кода:
pthread_t thread;
pthread_attr_t attr;
...
pthread_attr_init(&attr);
pthread_create(&thread, &attr, init_routine, NULL);
pthread_attr_destroy(&attr);
pthread_t thread;
...
pthread_create(&thread, NULL, init_routine, NULL);Процедура точки входа
В вызове процедуры pthread_create должна указываться процедура точки входа. Эта процедура, описанная в программе, аналогична функции main процесса. Она является первой процедурой, запускаемой в новой нити. При выходе из этой процедуры нить автоматически завершается.
Процедура точки входа имеет один параметр - указатель типа void, который задается при вызове pthread_create. Он может применяться для передачи указателя на некоторые данные - например, на строку или структуру. Создающая (вызывающая процедуру pthread_create) и создаваемая нить должны согласовать фактический тип этого указателя.
Процедура точки входа возвращает указатель типа void. После завершения нити этот указатель хранится библиотекой нитей до момента удаления нити. За дополнительной информацией о применении этого указателя обратитесь к разделу Возврат информации из нити.
Возвращаемая информация
Процедура pthread_create возвращает идентификатор новой нити. Вызывающая нить может использовать этот идентификатор для выполнения различных действий с созданной нитью.
В зависимости от заданных для нитей параметров планирования, новая нить может начать работу до того, как процедура pthread_create вернет значение вызывающей программе. Может оказаться, что в момент завершения работы функции pthread_create новая нить уже будет завершена. В этом случае процедура pthread_create возвращает в параметре thread неправильный идентификатор. Поэтому при работе с процедурами библиотеки нитей, которым передается идентификатор нити в качестве параметра, необходимо сравнивать результаты операций с кодом ошибки ESRCH.
Если процедура pthread_create не может создать нить, то параметр thread содержит недопустимый идентификатор, а процедура возвращает код ошибки. Дополнительная информация приведена в разделе Пример программы с несколькими нитями.
Работа с идентификаторами нитей
Идентификатор новой нити передается вызывающей нити в параметре thread. Идентификатор текущей нити можно получить с помощью процедуры pthread_self.
ИД нити - это объект со скрытой реализацией типа pthread_t. В AIX тип данных pthread_t представляет собой целое число (integer). В других системах он может быть структурой, указателем или другим типом.
Для повышения переносимости программ, использующих библиотеку нитей, ИД нити должен всегда обрабатываться как объект со скрытой реализацией. По этой причине сравнение идентификаторов нитей должно выполняться с помощью процедуры pthread_equal. Не используйте оператор сравнения C (==), так как тип данных pthread_t может отличаться от арифметического типа данных или указателя.