Студопедия

КАТЕГОРИИ:


Архитектура-(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 служила системная функция DosKillThread. Эта функция описывалась прототипом

APIRET DosKillThread(TID tid)

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

Для самоуничтожения нити, иными словами прекращения ее работы по инициативе процедуры самой нити в операционных системах Unix, использующих стандарт POSIX, служит функция с прототипом

int pthread_exit(int code),

параметр которой задает код возврата, а для прекращения работы нити по инициативе другой нити служит системная функция с именем pthread_cancel. Она имеет прототип

int pthread_cancel(pthread_t tid),

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

Средства управления нитями лучше всего развиты в современных версиях Unix, в частности в Linux. Прекращение работы нити по явному приказу другой нити является довольно решительной мерой, учитывая, что нити процесса выполняют общую работу. Поэтому уничтожение нити в общем случае может иметь непредусмотренный побочный эффект на результаты работы всего процесса. Эти соображения привели в Unix к введению средств, гибко управляющих возможностью уничтожения нити. В настоящее время такие средства состоят из двух вспомогательных функций pthruat_setcanceltype() и pthread_setcancelstate() и состояний нити относительно возможности уничтожениџ. Эти ёостояния называются асинхѐонно отменяемым, синхронно отменяемым и неотменяемым. Асинхронно отменяемое состояние отвечает отсутствию ограничений на уничтожение нити – нить в этом состоянии можно уничтожить в любой момент и в любом месте ее выполнения. Синхронно отменяемая нить может быть уничтожена только тогда, когда она находится в некоторых точках своего выполнения – так называемых точках отмены (cancel points). Нить, находящуюся в неотменяемом состоянии, невозможно уничтожить приказом со стороны, пока она по своей инициативе не сменит это состояние. Переключение между отменяемыми состояниями и неотменяемым производится с помощью функции pthread_setcancelstate(), имеющей прототип

int pthread_setcancelstate(int state, int *oldstate),

где первый аргумент должен задаваться одной из символических констант PTHREAD_CANCEL_DISABLE и PTHREAD_CANCEL_ENABLE, определяющими состояние после его переустановки этой функцией. Второй аргумент в случае неиспользования может задаваться как NULL, в противном случае он передает адрес переменной для записи кода старого состояния отменяемости (представимого этими же символическими константами). Заметим, что рассматриваемая функция действует на ту именно нить, которая выполняет эту функцию и не предоставляет никаких возможностей для смены состояния отменяемости другой нити.

Переключение между асинхронно отменяемым и синхронно отменяемым состояниями нити задается функцией pthread_setcanceltype(), имеющей прототип

int pthread_setcanceltype(int type, int *oldtype),

где первый аргумент должен задаваться одной из символических констант PTHREAD_CANCEL_DEFERRED и PTHREAD_CANCEL_ASYNCHRONOUS, причем первая константа дает состояние именно синхронно отменяемой нити, а второй аргумент служит для возврата предыдущего состояния отменяемости, но может задаваться значением NULL, если такая информация не требуется.

Точка отмены явно создается между двумя последовательными вызовами специальной функции pthread_testcancel(), не имеющей аргументов. Такая конструкция отмечает место процедуры нити, в которой она может быть уничтожена. Кроме явного указания точек отмены, операционная система вводит в программу неявные точки отмены, в которых по усмотрению разработчиков ОС допустимо относительно безболезненное уничтожение нитей. К сожалению, такие точки не всегда достаточно документированы в справочной системе. Рекомендуется искать информацию о них с помощью вызова справки

man pthread_cancel

Точки отмены неявно могут устанавливаться длительно выполняющими функциями ввода-вывода, в частности вывода на экран.

Описанные средства демонстрируются примером программы для Unix, приведенной в листинге 8.3.1.

 

#include <pthread.h>

#include <stdio.h>

#include <signal.h>

char lbuk[ ]="abcdefghijklmnoprstuwxyz";

pthread_t tid1, tid2, tid3;

 

void procthread1(void *arg)

{int k, j;

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

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

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

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

if (k= =5) {pthread_kill(tid2, SIGSTOP);

printf("-Suspend thread2");}

if (k= =11) {pthread_kill(tid2, SIGCONT);

printf("-Resume thread2");}

printf("\n");

usleep(800000);

}

}

 

void procthread2(void *arg)

{int k, j;

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

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

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

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

if (k= =5) {pthread_cancel(tid3);

printf("-Terminate thread3");}

printf("\n");

usleep(1300000);

}

}

 

void procthread3(void *arg)

{int k, j;

// pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);

/// pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

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

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

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

for (j=0; j<(int)arg; j++)

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

printf("\n");

usleep(1100000);

}

}

 

int main()

{int k;

int rc;

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

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

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

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

 

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

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

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

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

printf("\n"); usleep(1000000);

}

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

printf("\033[0m");

return 0;

}

Листинг 8.3.1 Уничтожение нити по явному приказу другой нити в Linux

 

В этой программе вторая нить, реализующая действия процедуры procthread2 на пятом шаге (при k=5), отдает приказ на уничтожение третьей нити (нити с процедурой procthread3).

Если убрать символы комментариев перед первым оператором третьей нити, то вызов функции pthread_setcancelstate() в этом операторе будет переключать эту нить в состояние неотменяемости, и при запуске программы можно наблюдать, что приказ на уничтожение нити в действительности не выполняется. Попытки же перевести указанную нить в состояние синхронной отменяемости не имеют явного эффекта из-за того, что операторы printf вывода на экран неявно создают точки отмены, на которых и происходит прекращение работы этой нити по приказу на ее уничтожение.

В операционных системах Windows для уничтожения процессов служит системная функция TerminateThread, которая имеет прототип

BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode).

Код возврата из завершившейся или принудительно прекращенной приказом TerminateThread нити может быть получен в другой нити того же процесса путем вызова вспомогательной функции GetExitCodeThread, которая имеет прототип

BOOL GetExitCodeThread(HANDLE hThread, DWORD *pExitCode).

Если задача, указанная аргументом hThread, в момент запроса кода возврата еще работает, то функция возвращает значение STILL_ACTIVE в качестве значения второго аргумента. Код возврата нормально завершающейся нити формирует функция завершения ExitThread, которая имеет прототип

void ExitThread(DWORD dwExitCode).

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

Аналогично рассмотренным выше примерам, функцию уничтожения нити в операционных системах Windows можно продемонстрировать изменением программы из листинга 8.2.2, вставив оператор

if (k= =5) TerminateThread(hthread3, 0)

после операторов

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

в процедуре procthread2.

 




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


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


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



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




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