pthread 简要使用指南(三) 线程的终止


    pthread_create()的帮助文档里面,明确指出,一个线程的终止有如下的四种方式:
    
    * 本线程中调用pthread_exit(),同一进程里面调用pthread_join()的其他线程可以获取该线程的退出值。
    * 本线程的线程函数start_routine执行结束返回。
    * 本线程被pthread_cancel()取消。
    * 本线程所在的进程退出。

    pthread_exit(), 原型:
    void pthread_exit(void *retval);
    该函数在线程中的作用,与exit()在进程中的作用类似。执行到pthread_exit(),线程将会直接终止,并使用pthread_exit的参数作为线程的退出状态值。如果线程是joinable的,其线程ID和退出状态值将一直保留到调用进程中的某个其他线程调用pthread_join函数。指针retval不能指向局部于调用线程的对象,因为线程终止时这些对象也消失。

    pthread_cancel(),原型:
    int pthread_cancel(pthread_t thread);
    pthread_cancel()发送一个取消请求给目标线程,该函数需要目标线程配合。目标线程如何操作,取决于该线程的可撤销状态及类型(cancelability state and type)。
    可撤销状态有两个值:PTHREAD_CANCEL_ENABLE,PTHREAD_CANCEL_DISABLE。该状态可以通过pthread_setcancelstate()函数来修改。这个状态决定该线程是否处理取消请求。如果PTHREAD_CANCEL_ENABLE,则处理取消请求,PTHREAD_CANCEL_DISABLE,则不处理取消请求。
    可撤销类型同样也有两个值:PTHREAD_CANCEL_DEFERRED,PTHREAD_CANCEL_ASYNCHRONOUS。该类型可以通过pthread_setcanceltype()函数来修改。可撤销状态为PTHREAD_CANCEL_ENABLE时,可撤销类型值才会被判断。PTHREAD_CANCEL_ASYNCHRONOUS 立即执行取消信号,PTHREAD_CANCEL_DEFERRED 运行到下一个取消点然后退出线程。

    PTHREAD_CANCEL_DEFERRED情形下,pthread_cancel()给目标线程设置一个取消标志。目标线程在运行中的某些地方会查看自己是否存在取消请求,如果有,就立刻终止执行后继代码并退出。这些查看是否存在取消请求的地方,称之为取消点(Cancelation-point)。

   下面的代码,是在suse linux中的pthread_cancel编程指南中例子的基础上修改得到:

#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

#define handle_error_en(en, msg) \
    do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

static void * thread_func(void *ignored_argument)
{
    int s;
    pthread_t *pthr = (pthread_t *)ignored_argument;

    /* Disable cancellation for a while, so that we don't
    immediately react to a cancellation request */

    s = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
    if (s != 0)
        handle_error_en(s, "pthread_setcancelstate");

    printf("thread_func(id %u (0x%x)): started; cancellation disabled\n",
            (unsigned int)(*pthr), (unsigned int)(*pthr));
    sleep(5);
    printf("thread_func(id %u (0x%x)): about to enable cancellation\n", 
            (unsigned int)(*pthr), (unsigned int)(*pthr));

    s = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    if (s != 0)
        handle_error_en(s, "pthread_setcancelstate");

    /* sleep() is a cancellation point */

    sleep(10);        /* Should get canceled while we sleep */

    /* Should never get here */

    printf("thread_func(id %u (0x%x)): not canceled!\n", 
            (unsigned int)(*pthr), (unsigned int)(*pthr));

    return NULL;
}

int main(void)
{
    pthread_t thr1;
    pthread_t thr2;
    void *res;
    int s;

    /* Start a thread and then send it a cancellation request */

    s = pthread_create(&thr1, NULL, &thread_func, (void*)&thr1);
    if (s != 0)
        handle_error_en(s, "pthread_create 1");

    s = pthread_create(&thr2, NULL, &thread_func, (void*)&thr2);
    if (s != 0)
        handle_error_en(s, "pthread_create 2");

    sleep(2);           /* Give thread a chance to get started */

    printf("main(): sending cancellation request\n");

    s = pthread_cancel(thr1);
    if (s != 0)
        handle_error_en(s, "pthread_cancel");

    /* Join with thread to see what its exit status was */

    s = pthread_join(thr1, &res);
    if (s != 0)
        handle_error_en(s, "pthread_join");

    if (res == PTHREAD_CANCELED)
        printf("main(): thread 1 was canceled\n");
    else
        printf("main(): thread 1 wasn't canceled (shouldn't happen!)\n");

    s = pthread_join(thr2, &res);
    if (s != 0)
        handle_error_en(s, "pthread_join");

    if (res == PTHREAD_CANCELED)
        printf("main(): thread 2 was canceled\n");
    else
        printf("main(): thread 2 wasn't canceled (shouldn't happen!)\n");

    exit(EXIT_SUCCESS);
}



你可能感兴趣的:(JOIN,thread,linux,null,SuSE,asynchronous)