Создание нового потока

Создание нового потока

Создание нового потока в программном коде осуществляет вызов:

int pthread_create(pthread_t* thread,

 const pthread_attr_t* attr, void*(*start_routine)(void*), void* arg);

где thread — NULL или указатель переменной типа pthread_t, значение которой будет загружено идентификатором созданного потока после успешного выполнения функции. Далее это значение (это и есть TID) может использоваться по тексту программы для идентификации созданного потока.

attr — NULL или указатель структуры типа pthread_attr_t. Если это значение NULL, то созданный поток будет иметь набор параметров, устанавливаемых по умолчанию. Если нет, то поток будет создан с параметрами, установленными в структуре attr. Модификация полей attr после создания потока (то есть после вызова функции) не оказывает никакого эффекта на параметры потока, и вообще говоря, структура attr может быть уничтожена сразу же после вызова pthread_create(). Документация предостерегает от прямой манипуляции значениями полей этой структуры, предлагая использовать для этого функции pthread_attr_init() и pthread_attr_set_*().

start_routine — функция типа void*()(void*), уже упоминавшаяся выше как функция потока; это тот код, который будет фактически выполняться в качестве отдельного потока. Если выполнение этой функции завершается по return, то происходит нормальное завершение потока с вызовом pthread_exit(), использующим значение, возвращаемое start_routine в качестве статуса завершения. (Исключением является поток, связанный с main(); он при завершении выполняет вызов exit().)

arg — указатель на блок данных, передаваемых start_routine в качестве входного параметра. Этот параметр подробно рассмотрен далее.

Чаще всего (однако совершенно необязательно) функция потока start_routine представляет собой бесконечный цикл, в котором выполняются некоторые действия с выходом из цикла в том случае, когда нужно завершить выполнение и уничтожить созданный поток. Выглядит это следующим образом:

// функция потока:

void* ThreadProc(void* data) {

 while (true) {

  // ... выполняется работа ...

  if (...) break;

  // после этого поток нам уже не нужен!

 }

 return NULL;

}

После успешного создания нового потока он начинает функционировать «параллельно» с породившим его потоком и другими потоками процесса (если быть совсем точными, то со всеми прочими потоками, существующими в системе, так как в QNX существует только одна стратегия диспетчеризации потоков PTHREAD_SCOPE_SYSTEM, и существует она глобально, на уровне всей системы). При этом после точки выполнения pthread_create() невозможно предсказать, какой поток получит управление: породивший, порожденный или вообще произвольный поток из другого процесса. Это важно учитывать при передаче новому потоку данных и других операциях начальной инициализации параметров внутри созданного потока.

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

Данный текст является ознакомительным фрагментом.