Unix - статьи


Досрочное завершение потока - часть 2


Первый вызов pthread_setcancelstate() запрещает досрочное завершение потока, второй – разрешает. Если запрос на досрочное завершение потока поступит в тот момент, когда поток игнорирует эти запросы, выполнение запроса будет отложено до тех пор, пока функция pthread_setcancelstate() не будет вызвана с аргументом PTHREAD_CANCEL_ENABLE. Что именно произойдет дальше, зависит от более тонких настроек потока. Рассмотрим пример программы (на диске вы найдете ее в файле canceltest.c)

#include <stdlib.h> #include <stdio.h> #include <pthread.h> int i = 0; void * thread_func(void *arg) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); for (i=0; i < 4; i++) { sleep(1); printf("I'm still running!\n"); } pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); printf("YOU WILL NOT STOP ME!!!\n"); } int main(int argc, char * argv[]) { pthread_t thread; pthread_create(&thread, NULL, thread_func, NULL); while (i < 1) sleep(1); pthread_cancel(thread); printf("Requested to cancel the thread\n"); pthread_join(thread, NULL); printf("The thread is stopped.\n"); return EXIT_SUCCESS; }

В самом начале функции потока thread_func() мы запрещаем досрочное завершение потока, затем выводим четыре тестовых сообщения с интервалом в одну секунду, после чего разрешаем досрочное завершение. Далее, с помощью функции pthread_testcancel(), мы создаем точку отмены (cancellation point) потока. Если досрочное завершение потока было затребовано, в этот момент поток должен завершиться. Затем мы выводим еще одно диагностическое сообщение, которое пользователь не должен видеть, если программа сработает правильно.

В главной функции программы мы создаем поток, затем дожидаемся, пока значение глобальной переменной i станет больше нуля (это гарантирует нам, что поток уже запретил досрочное завершение) и вызываем функцию pthread_cancel(). После этого мы переходим к ожиданию завершения потока с помощью pthread_join(). Если вы скомпилируете и запустите программу, то увидите, что поток распечатает четыре тестовых сообщения I’m still running! (после первого сообщения главная функция программы выдаст запрос на завершение потока).

Поскольку поток завершится досрочно, последнего тестового сообщения вы не увидите. Интересна роль функции pthread_testcancel(). Как уже отмечалось, эта функция создает точку отмены потока. Зачем нужны особые точки отмены? Дело в том, что даже если досрочное завершение разрешено, поток, получивший запрос на досрочное завершение, может завершить работу не сразу. Если поток находится в режиме отложенного досрочного завершения (именно этот режим установлен по умолчанию), он выполнит запрос на досрочное завершение, только достигнув одной из точек отмены. В соответствии со стандартом POSIX, точками отмены являются вызовы многих «обычных» функций, например open(), pause() и write(). Про функцию printf() в документации сказано, что она может быть точкой отмены, но в Linux при попытке остановиться на printf() происходит нечто странное – поток завершается, но pthread_join() не возвращает управления. Поэтому мы создаем явную точку отмены с помощью вызова pthread_testcancel().

Впрочем, мы можем выполнить досрочное завершение потока, не дожидаясь точек останова. Для этого необходимо перевести поток в режим немедленного завершения, что делается с помощью вызова pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); В этом случае беспокоиться о точках останова уже не нужно. Вызов pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); снова переводит поток в режим отложенного досрочного завершения.

Тема потоков практически неисчерпаема (простите за каламбур), но мы посвятим потокам только лишь , в которой рассмотрим вопросы синхронизации и атрибуты потоков.




- Начало -  - Назад -  - Вперед -



Книжный магазин