5

我正在使用pthread_create()andpthread_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()

4

2 回答 2

9

默认情况下,您的线程是使用取消类型 PTHREAD_CANCEL_DEFERRED创建的,这意味着您需要确保您的线程具有所谓的取消点。即,检查取消请求并对其做出反应的点。

此页面包含保证是取消点的功能列表。示例是一些 thesleep()和 pthread 函数。pthread_testcancel()如果您只需要一个函数来纯粹测试线程是否已被取消,您也可以使用,而不是其他。

另一种选择是PTHREAD_CANCEL_ASYNCHRONOUS通过使用将您的线程取消类型设置为pthread_setcanceltype(),这将使您的线程即使没有取消点也可以取消。但是,系统仍然可以自由选择何时实际取消线程,并且您需要非常小心以确保系统在取消时不会处于不一致的状态(通常意味着避免任何系统调用和类似 - 请参阅异步取消安全功能列表- 很短!)。

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

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

于 2012-06-30T08:00:53.373 回答
0

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

于 2012-06-30T07:46:42.337 回答