printf("The %dth prime number is %d.\n", which_prime, prime);
return 0;
}
4.1.4. Подробнее об идентификаторах потоков
Иногда в программе возникает необходимость определить, какой поток выполняет ее в данный момент. Функция pthread_self()
возвращает идентификатор потока, в котором она вызвана. Для сравнения двух разных идентификаторов предназначена функция pthread_equal()
.
Эти функции удобны для проверки соответствия заданного идентификатора текущему потоку. Например, поток не должен вызывать функцию pthread_join()
, чтобы ждать самого себя (в подобной ситуации возвращается код ошибки EDEADLK
). Избежать этой ошибки позволяет следующая проверка:
if (!pthread_equal(pthread_self(), other_thread)) pthread_join(other_thread, NULL);
4.1.5. Атрибуты потоков
Потоковые атрибуты — это механизм настройки поведения отдельных потоков. Вспомните, что функция pthread_create()
принимает аргумент, являющийся указателем на объект атрибутов потока. Если этот указатель равен NULL
, поток конфигурируется на основании стандартных атрибутов.
Для задания собственных атрибутов потока выполните следующие действия.
1. Создайте объект типа pthread_attr_t
.
2. Вызовите функцию pthread_attr_init()
, передав ей указатель на объект. Эта функция присваивает неинициализированным атрибутам стандартные значения.
3. Запишите в объект требуемые значения атрибутов.
4. Передайте указатель на объект в функцию pthread_create()
.
5. Вызовите функцию pthread_attr_destroy()
, чтобы удалить объект из памяти. Сама переменная pthread_attr_t
не удаляется; ее можно проинициализировать повторно с помощью функции pthread_attr_init()
.
Один и тот же объект может быть использован для запуска нескольких потоков. Нет необходимости хранить объект после того, как поток был создан.
Для большинства Linux-приложений интерес представляет один-единственный атрибут (остальные используются в приложениях реального времени): pthread_join()
, чтобы запросить это значение. Только тогда ресурсы потока считаются освобожденными. С другой стороны, отсоединенный поток, завершившись, сразу уничтожается. Другие потоки не могут вызвать по отношению к нему функцию pthread_join()
или получить возвращаемое им значение.
Чтобы задать статус отсоединения потока, воспользуйтесь функцией pthread_attr_setdetachstate()
. Первый ее аргумент — это указатель на объект атрибутов потока, второй — требуемый статус. Ожидаемые потоки создаются по умолчанию, поэтому в качестве второго аргумента имеет смысл указывать только значение PTHREAD_CREATE_DETACHED
.
Программа, представленная в листинге 4.5, создает отсоединенный поток, устанавливая соответствующим образом атрибуты потока.
#include
void* thread_function(void* thread_arg) {
/* Тело потоковой функции... */
}
int main() {
pthread_attr_t attr;
pthread_t thread;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &attr, &thread_function, NULL);
pthread_attr_destroy(&attr);
/* Тело основной программы... */
/* Дожидаться завершения второго потока нет необходимости. */
return 0;
}
Даже если поток был создан ожидаемым, его позднее можно сделать отсоединенным. Для этого нужно вызвать функцию pthread_detach()
. Обратное преобразование невозможно.
4.2. Отмена потока
Обычно поток завершается при выходе из потоковой функции или вследствие вызова функции pthread_exit()
. Но существует возможность запросить из одного потока уничтожение другого. Это называется отменой, или принудительным завершением, потока.