КАТЕГОРИИ: Архитектура-(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; Просмотров: 332; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |