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

ЖАНРЫ

Параллельное и распределенное программирование на С++
Шрифт:

// Программа 4.2

void *task1(void *X)

{

int *Temp;

Temp = static_cast<int *>(X);

for(int Count = 1;Count < *Temp;Count++){

cout << «work from thread A: " << Count << " * 2 = "

<< Count * 2 << endl;

}

cout << «Thread A complete» << endl;

}

void *task2(void *X)

{

int *Temp;

Temp = static_cast<int *>(X);

for(int Count = 1;Count < *Temp;Count++){

cout << «work from thread B: " << Count << " + 2 = "

<< Count + 2 << endl;

}

cout <<

«Thread B complete» << endl;

}

В программе 4.2 функции taskl и task2 выполняют цикл, количество итераций которого равно числу, переданному каждой функции в качестве параметра. Одна функция увеличивает переменную цикла на два, вторая — умножает ее на два, а затем каждая из них отправляет результат в стандартный поток вывода данных. По выходу из цикла каждая функция выводит сообщение о завершении выполнения потока. Инструкции по компиляции и выполнению программ 4.1 и 4.2 содержатся в профиле программы 4.1.

[ Профиль программы 4.1

Имя программы •program4-12.cc

* Описание Принимает целочисленное значение из командной строки и передает функциям: потоков. Каждая функция выполняет цикл, в котором переменная цикла увеличивается (в одной функции на два, а в другой в два раза), а затем результат отсылается в стандартный поток вывода данных. Код основного потока выполнения приведен в программе 4.1, а код функций — в программе 4.2.

Требуемая библиотека libpthread

Требуемые заголовки <pthread.h> <iostream> <stdlib.h>

Инструкции по компиляции и компоновке программ

с++ -о program4-12 program4-12.cc -lpthread

Среда для тестирования SuSE Linux 7.1, gcc 2.95.2,

Инструкции по выполнению ./program4-12 34

Примечания Эта программа требует задания аргумента командной строки.

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

Получение идентификатора потока

Как упоминалось выше, процесс разделяет все свои ресурсы с потоками, используя лишь собственное адресное пространство. Потокам в собственное пользование выделяются весьма небольшие их объемы. Идентификатор потока (id) — это один из ресурсов, уникальных для каждого потока. Чтобы узнать свой идентификатор, потоку необходимо вызвать функцию pthread_self .

Синопсис

#include <pthread.h>

pthread_t pthread_self(void)

Эта функция аналогична функции getpid для процессов. При создании потока его идентификатор возвращается его создателю или вызывающему потоку. Однако идентификатор потока не становится известным созданному потоку автоматически. Но если уж поток обладает собственным идентификатором, он может передать его (предварительно узнав его сам) другим потокам процесса. Функция pthread_self возвращает идентификатор потока, не определяя никаких кодов ошибок.

Вот пример вызова этой функции:

pthread_t ThreadId;

ThreadId = pthread_self;

Поток вызывает функцию pthread_self, а значение, возвращаемое ею (идентификатор потока), сохраняет в переменной ThreadId типа pthread_t.

Присоединение потоков

Функция pthread_join используется для присоединения или воссоединения потоков выполнения

в одном процессе. Эта функция обеспечивает приостановку выполнения вызывающего потока до тех пор, пока не завершится заданный поток. По своему Действию эта функция аналогична функции wait , используемой процессами. Эту функцию может вызвать создатель потока, после чего он будет ожидать до тех пор, пока не завершится новый (созданный им) поток, что, образно говоря, можно назвать воссоединением потоков выполнения. Функцию pthread_join могут также вызывать равноправные потоки, если потоковый дескриптор является глобальным. Это позволяет любому потоку соединиться с любым другим потоком выполнения в процессе. Если вызы вающий поток аннулируется до завершения заданного (для присоединения) потока,этот заданный поток не станет открепленным (detached) потоком (см. следующий раздел) Если различные равноправные потоки одновременно вызовут функцию pthread_join для одного и того же потока, его дальнейшее поведение не определено.

Синопсис

#include <pthread.h>

int pthread_join(pthread_t thread, void **value_ptr);

Параметр thread представляет поток, завершения которого ожидает вызывающий поток. При успешном выполнении этой функции в параметре value_ptr будет записан статус завершения потока. Статус завершения — это аргумент, передаваемый при вызове функции pthread_exit завершаемым потоком. При неудачном выполнении эта функция возвратит код ошибки. Функция не будет выполнена успешно, если заданный поток не является присоединяемым, т.е. создан как открепленный. Об успешном выполнении этой функции не может быть и речи, если заданный поток попросту не существует.

Функцию pthread_join необходимо вызывать для всех присоединяемых потоков. После присоединения потока операционная система сможет снова использовать память, которую он занимал. Если присоединяемый поток не был присоединен ни к одному потоку или если поток, который вызывает функцию присоединения, аннулируется, то заданный поток будет продолжать использовать свою память. Это состояние аналогично зомбированному процессу, в которое переходит сыновний процесс, когда его родитель не принимает статус завершения потомка, и этот «беспризорный» сыновний процесс продолжает занимать структуру в таблице процессов.

Создание открепленных потоков

Открепленным называется завершаемый поток, который не присоединился или завершения которого не дождался другой поток. При завершении потока ограниченные ресурсы, которые он использовал, включая его идентификатор, освобождаются и возвращаются системе. Потокам нет необходимости получать статус завершения. Попытка со стороны любого потока вызвать функцию pthread_join для открепленного потока обречена на неудачу. Существует функция pthread_detach , которая открепляет поток, заданный параметром thread . По умолчанию все потоки создаются как присоединяемые, если атрибутным объектом не обусловлено иное. Эта функция позволяет открепить уже существующие присоединяемые потоки. Если поток не завершен, обращение к этой функции не обеспечит его завершения.

Синопсис

#include <pthread.h>

int pthread_detach(pthread_t thread thread);

При успешном выполнении эта функция возвращает число 0 , в противном случае— код ошибки. Функция pthread_detach не будет успешной, если заданный поток уже откреплен или поток, заданный параметром thread, не был обнаружен.

Вот пример открепления уже существующего присоединяемого потока:

pthread_create(&threadA,NULL,taskl,NULL);

Поделиться с друзьями: