Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Ожидание завершения нити

Другой формой управления нитями внутри программы являются функции ожидания завершения нити. В определенной степени эта функция аналогична функциям ожидания окончания процессов, но относится к уровню нитей. В конечном счете она предназначена для той же цели – согласования совместной работы нитей на основе самого глобального по смыслу действия – полного завершения работы отдельной выполняемой программной единицы.

В операционной системе OS/2 функция ожидания завершения нити называется DosWaitThread и имеет прототип

APIRET DosWaitThread(PTID ptid, ULONG option).

Эта функция в данной операционной системе предназначена для целого спектра действий. Она может быть использована для ожидания завершения конкретной нити того же процесса, заданной идентификатором в первом аргументе. (Отметим, что этот аргумент – возвращаемый!) При этом второй аргумент должен быть задан символической константой DCWW_WAIT или просто ее значением, равным нулю. Она может быть использована для получения информации, завершена ли конкретная нить данного процесса. Тогда второй аргумент должен задаваться константой DCWW_NOWAIT, равной 1. Результаты выполнения функции DosWaitThread при этом выдаются через код возврата. Именно, если указанная в вызове нить завершена, возвращается нулевой код, если не завершена, возвращается код ХХХХ, представляемый символической константой ХХХ_ХХХХХ.

Эта же функция DosWaitThread может быть использована для приостановки выполняющей ее нити до тех пор, пока какая-то другая нить этого же процесса не будет завершена. Для этих целей функция DosWaitThread должна быть вызвана с нулевым значением переменной для идентификатора нити, на которую указывает первый аргумент функции. С этой целью можно использовать последовательность операторов

tid=0; DosWaitThread(&tid, DCWW_WAIT),

где переменная tid определена как имеющая тип TID. В результате такого выполнения функции DosWaitThread будет получено значение идентификатора (в переменной tid – для указанного примера), обозначающего ту нить, которая была завершена после вызова этой функции.

Наконец, эта же функция может быть использована без ожидания для получения информации, какая нить в данном процессе была завершена последней. В этом применении вызов функции должен иметь второй аргумент, равный DCWW_NOWAIT, а первый аргумент быть указателем на нулевое значение переменной для идентификатора нити.

В операционной системе Unix, поддерживающей стандарт POSIX, для ожидания нити служит функция pthread_join, имеющая прототип

int pthread_join(pthread_t tid, void** status).

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

тип_результата restatus;

void *status=&restatus;

...

pthread_exit(&restatus); // в конце процедуры нити

...

pthread_join(tid, &status);

< анализ значения *status>

либо в простейшем случае может быть использовано явное преобразование типа.

 

#include <stdio.h>

char lbuk[ ]="abcdefghijklmnoprstvuwxy";

pthread_t tid1, tid2, tid3;

 

void procthread1(void *arg)

{int k, j;

for (k=0; k<24; k++) {

// установить вывод в позицию (20,k+1) и синий цвет

printf("\033[%02d;20H",k+1); printf("\033[1;34m");

for (j=0; j<(int)arg; j++) printf("%c",lbuk[k]);

printf("\n");

usleep(1000000);

}

}

 

void procthread2(void *arg)

{int k, j;

for (k=0; k<24; k++) {

//установить вывод в позицию (40,k+1) и зеленый цвет

printf("\033[%02d;40H",k+1); printf("\033[1;32m");

for (j=0; j<(int)arg; j++) printf("%c",lbuk[k]);

printf("\n");

usleep(1000000);

}

}

 

void procthread3(void *arg)

{int k, j, *rc;

for (k=0; k<7; k++) {

// установить вывод в позицию (60,k+1) и красный цвет

printf("\033[%02d;60H",k+1); printf("\033[1;31m");

for (j=0; j<(int)arg; j++) printf("%c",lbuk[k]);

printf("\n");

usleep(1000000);

}

printf("\033[%02d;60H",k+1); printf("\033[1;31m");

printf("Waiting End thread1\n");

pthread_join(tid1, (void**)&rc);

printf("\033[%02d;60H",k+1); // установить вывод в позицию (60,k+2)

printf("\033[1;31m"); // и красный цвет

printf("End waiting\n");

for (k=9; k<24; k++) {

printf("\033[%02d;60H",k+1); // установить вывод в поз. (60,k+1)

printf("\033[1;31m"); // и красный цвет

for (j=0; j<(int)arg; j++) printf("%c",lbuk[k]);

printf("\n");

usleep(1000000);

}

}

 

void main()

{int k;

printf("\033[2J\n");//clrscr();

pthread_create(&tid1, NULL, (void*)procthread1, (void*)2);

pthread_create(&tid2, NULL, (void*)procthread2, (void*)3);

pthread_create(&tid3, NULL, (void*)procthread3, (void*)4);

for (k=0; k<24; k++) {

printf("\033[%02d;1H",k+1); //установить вывод в позицию (1,k+1) и белый цвет

printf("\033[1;37m");

printf("%c++\n",lbuk[k]);

if (k==9)

{pthread_cancel(tid2); //!!!

printf("\033[%02d;1H",k+1); // установить вывод в позицию (1,k+1)

printf("Kill Thread2\n");

}

usleep(1500000);

}

printf("\033[%02d;30H",24); // установить вывод в позицию (30,24)

pthread_join(tid1,NULL); pthread_join(tid2,NULL); pthread_join(tid3,NULL);

printf("\033[0m"); // вернуть вывод на экран к стандартному цвету

}

Листинг 8.5.1. Программа с ожиданием завершения нитей для Unix

 

В программе с целью упрощения (ввиду того, что код возврата из процедуры не используется) значение кода завершения, возвращаемое с помощью функции pthread_join, описано как целочисленное (в виде int *rc;), а при вызове функции для второго аргумента используется преобразование типов в виде (void**)&rc. После вызова функции ожидания pthread_join третья нить, обратившаяся к этой функции, приостанавливается до тех пор, пока не завершится указанная в нем нить, т.е. первая нить. Завершение этой первой нити приводит к возобновлению действий приостановленной третьей нити. Для более легкого восприятия содержательных ситуаций программа процесса снабжена выдачей сообщений о приостановке и возобновлении нити.

В операционных системах Windows для ожидания завершения нити служит уже частично рассматривавшаяся универсальная функция ожидания WaitForSingleObject. Для ожидания завершения нити в качестве первого аргумента этой функции следует взять хэндл ожидаемой нити, а в качестве второго - значение предельного времени ожидания, в простейшем случае INFINITE. Каких-либо особенностей, отличающих ее от других форм ожидания, эта функция не имеет при использовании для ожидания нити.

Следующие фрагменты программы, представленные в листинге 8.5.2, демонстрируют простейшее ожидание завершения нити. Отсутствующие части программы совпадают с ее прототипом, записанным в листинге 8.2.2. Программа, восстановленная по указанным фрагментам, функционирует в Windows совершенно так, как было описано выше для программы в листинге 8.5.1, предназначенной для Unix.

 

#include <windows.h>

...

DWORD WINAPI procthread3(void *arg)

{int k, j;

COORD pos;

for (k=0; k<7; k++)

{// установка позиции вывода (60,k+1) и красный цвет вывода

for (j=0; j<(int)arg; j++) printf("%c",lbuk[k]);

...

Sleep(1000);

}

// установка позиции вывода (60,k+1) и красный цвет вывода

...

printf("Waiting End thread1");

LeaveCriticalSection(&csec);

WaitForSingleObject(hthread1, INFINITE);

// установка позиции вывода (60,k+1) и красный цвет вывода

...

printf("End waiting");

LeaveCriticalSection(&csec);

for (k=9; k<24; k++) {

// установка позиции вывода (60,k+1) и красный цвет вывода

...

for (j=0; j<(int)arg; j++) printf("%c",lbuk[k]);

LeaveCriticalSection(&csec);

Sleep(1000);

}

}

 

void main()

{DWORD threadid1, threadid2, threadid3;

...

for (k=0; k<24; k++) {

...

printf("%c++",lbuk[k]);

if (k==9)

{TerminateThread(hthread2, 0);

pos.X=1; pos.Y=k+1; SetConsoleCursorPosition(hstdout,pos);

printf("Kill Thread2");

}

LeaveCriticalSection(&csec);

Sleep(1500);

}

pos.X=30; pos.Y=24; SetConsoleCursorPosition(hstdout,pos);

...

}

Листинг 8.5.2. Программа с ожиданием завершения нитей для Windows

 

Данная программ принципиально не отличается от рассмотренных.

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

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

<== предыдущая лекция | следующая лекция ==>
Приостановка и повторный запуск нити | Абстрактные критические секции
Поделиться с друзьями:


Дата добавления: 2014-01-05; Просмотров: 317; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.042 сек.