□ schedparam
— это напарник атрибута schedpolicy
и позволяет управлять планированием потоков, выполняющихся с типом планирования SCHED_OTHER
. Мы рассмотрим пример его применения чуть позже в этой главе.
□ inheritsched
— этот атрибут принимает одно из двух значений: PTHREAD_EXPLICIT_SCHED
и PTHREAD_INHERIT_SCHED
. По умолчанию значение атрибута PTHREAD_EXPLICIT_SCHED
, что означает планирование, явно заданное атрибутами. Если задать PTHREAD_INHERIT_SCHED
, новый поток будет вместо этого применять параметры, используемые потоком, создавшим его.
□ scope
— этот атрибут управляет способом вычисления параметров планирования потока. Поскольку ОС Linux в настоящее время поддерживает единственное значение PTHREAD_SCOPE_SYSTEM
, мы не будем рассматривать его в дальнейшем.
□ stacksize
— этот атрибут управляет размером стека при создании потока, задается в байтах. Это часть необязательного раздела стандарта и поддерживается только в тех реализациях, у которых определено значение _PTHREAD_THREAD_ATTR_STACKSIZE
. Linux по умолчанию реализует потоки со стеком большого размера, поэтому этот атрибут в ОС Linux избыточен.
Выполните упражнение 12.5.
Упражнение 12.5. Установка атрибута отсоединенного состояния
В примере с отсоединенным или обособленным потоком thread5.c вы создаете атрибут потока, задаете состояние потока как отсоединенное и затем создаете с помощью этого атрибута поток. Теперь, когда закончится дочерний поток, он вызовет обычным образом pthread_exit
. В это время исходный поток больше не ждет созданный им поток для присоединения. В данном примере используется простой флаг thread_finished
, чтобы позволить потоку main
определить, закончился ли дочерний поток, и показать, что потоки все еще совместно используют переменные.
#include
#include
#include
#include
void *thread_function(void *arg);
char message[] = "Hello World";
int thread_finished = 0;
int main() {
int res;
pthread_t a_thread;
pthread_attr_t thread_attr;
res = pthread_attr_init(&thread_attr);
if (res != 0) {
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setdetachstate(&thread_attr,
PTHREAD_CREATE_DETACHED);
if (res != 0) {
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, &thread_attr,
thread_function, (void *)message);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
(void)pthread_attr_destroy(&thread_attr);
while (!thread_finished) {
printf("Waiting for thread to say it's finished...\n");
sleep(1);
}
printf("Other thread finished, bye!\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
printf("thread_function is running. Argument was %s\n", (char *)arg);
sleep(4);
printf("Second thread setting finished flag, and exiting now\n");
thread_finished = 1;
pthread_exit(NULL);
}
Вывод не принесет сюрпризов:
$ ./threads
Waiting for thread to say it's finished...
thread_function is running. Argument was Hello World
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Waiting for thread to say it's finished...
Second thread setting finished flag, and exiting now
Other thread finished, bye!
Как видите, установка отсоединенного состояния позволяет второму потоку завершиться независимо, без необходимости исходному потоку ждать этого события.
Как это работает
В исходном тексте программы два важных фрагмента:
pthread_attr_t thread_attr;
res = pthread_attr_init(&thread_attr);
if (res != 0) {
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
который объявляет атрибут потока и инициализирует его, и
res = pthread_attr_setdetachstatе(&thread_attr, PTHREAD_CREATE_DETACHED);
if (res != 0) {
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
который устанавливает значения атрибутов для задания отсоединенного состояния потока.
К другим незначительным отличиям относится создание потока с передачей адреса атрибутов:
Читать дальше