pthread_cancel()函数无法终止线程

时间:2012-06-30 05:11:51

标签: c multithreading pthreads

我正在使用pthread_create()pthread_cancel()函数来创建多线程程序,但我注意到pthread_cancel()并没有真正终止它应该的线程。

void check(void *param){
    header_t *Bag = (header_t *) param;
    pthread_t timer_thread;
    while(true){
        if(Bag->size && TIMER_OFF){
            pthread_create(&timer_thread, NULL, (void *) &timer, (void *) Bag);
            printf("\nCREATE THREAD ID = %d\n", timer_thread);
            // ADD
        }
        else if(!TIMER_OFF && Bag->size >= 2 && Bag->next->time <= CURRENT_APT_TIME && CRRENT_TAG != Bag->next->tag){
            printf("\nOLD THREAD ID = %d TO BE CANCELLED\n", timer_thread);
            pthread_cancel(timer_thread);
            pthread_create(&timer_thread, NULL, (void *) &timer, (void *) Bag);
            printf("\nNEW THREAD ID = %d\n", timer_thread);
            // Replace
        }
        Sleep(1);
    }
}

计时器函数void timer(void *)正是它的声音,我已经包含几行来打印出自己的线程ID。

经过测试,可以看到以下内容:

...

OLD THREAD ID = 6041240 TO BE CANCELLED

NEW THREAD ID = 6046456

...

THREAD ID EXECUTING = 6041240

所以调用pthread_cancel()

没有终止定时器功能

2 个答案:

答案 0 :(得分:5)

默认情况下,您的主题是使用cancel type PTHREAD_CANCEL_DEFERRED创建的,这意味着您需要确保您的主题具有所谓的取消点。也就是说,检查取消请求并作出反应的点。

This page包含一系列保证为取消点的函数。示例是sleep()和pthread函数中的一些。如果你只需要一个函数来纯粹测试线程是否被取消,你也可以使用pthread_testcancel()

另一种选择是使用PTHREAD_CANCEL_ASYNCHRONOUS将线程的canceltype设置为pthread_setcanceltype(),这样即使没有取消点,您的线程也会被取消。但是,系统仍然可以自由选择何时实际取消线程,并且您需要非常小心地确保系统在取消时不会处于不一致状态(通常意味着避免任何系统调用和相似 - 请参阅Async-cancel-safe functions列表 - 简短!)。

通常,异步取消应该仅用于或多或少的“纯”处理线程,而执行系统调用的线程和类似的线程更好地通过延迟取消和小心放置取消点来实现。

此外,只要您不是detaching your thread(通过其属性创建分离,或在创建后调用pthread_detach()),您就需要调用pthread_join()在计时器线程上确保在取消它之后清除所有资源。否则,您可能最终处于没有任何备用线程资源的状态,您无法创建任何新线程。

答案 1 :(得分:0)

pthread_cancel()的默认取消方法被延迟取消。所以当您调用pthread_cancel()时,它在指定的线程到达取消点之前不会真正取消。您应该调用pthread_setcanceltype来为你的主题设置另一个取消方法。