2

我这里有一个难题,我无法解决,也没有在网上找到正确的答案:

我创建了一个带有清理路由的分离线程,问题是在我的 Imac 和 Ubuntu 9.1(双核)上。我无法正确取消休闲代码中的分离线程:

#include <iostream>
#include <pthread.h>
#include <sched.h>
#include <signal.h>

#include <time.h>

pthread_mutex_t mutex_t;

using namespace std;

static void cleanup(void *arg){
    pthread_mutex_lock(&mutex_t);
    cout << " doing clean up"<<endl;
    pthread_mutex_unlock(&mutex_t);
}


static void *thread(void *aArgument)
{

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);

    pthread_cleanup_push(&cleanup,NULL);
    int n=0;
    while(1){
        pthread_testcancel();
        sched_yield();
        n++;

        pthread_mutex_lock(&mutex_t);
        cout << " Thread 2: "<< n<<endl; // IF I remove this endl;  --> IT WORKS!!??
        pthread_mutex_unlock(&mutex_t);

    }
    pthread_cleanup_pop(0);

    return NULL;
}


int main()
{

    pthread_t thread_id;

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

    int error;

    if (pthread_mutex_init(&mutex_t,NULL) != 0) return 1;

    if (pthread_create(&thread_id, &attr, &(thread) , NULL) != 0) return 1;

    pthread_mutex_lock(&mutex_t);
    cout << "waiting 1s for thread...\n" <<endl;
    pthread_mutex_unlock(&mutex_t);

    int n =0;

    while(n<1E3){
        pthread_testcancel();
        sched_yield();
        n++;

        pthread_mutex_lock(&mutex_t);
        cout << " Thread 1: "<< n<<endl;
        pthread_mutex_unlock(&mutex_t);
    }

    pthread_mutex_lock(&mutex_t);
    cout << "canceling thread...\n" <<endl;
    pthread_mutex_unlock(&mutex_t);

    if (pthread_cancel(thread_id) == 0)
    {
        //This doesn't wait for the thread to exit
        pthread_mutex_lock(&mutex_t);
        cout << "detaching thread...\n"<<endl;
        pthread_mutex_unlock(&mutex_t);

        pthread_detach(thread_id);

        while (pthread_kill(thread_id,0)==0)
        {
                sched_yield();
        }

        pthread_mutex_lock(&mutex_t);
        cout << "thread is canceled";
        pthread_mutex_unlock(&mutex_t);

    }

    pthread_mutex_lock(&mutex_t);
    cout << "exit"<<endl;
    pthread_mutex_unlock(&mutex_t);

    return 0;
}

当我用 printf() 替换 Cout 时,我工作到最后“退出”,但是在 cout(甚至锁定)的情况下,可执行文件在输出“分离线程......

从专业人士那里知道这将是非常酷的,这里的问题是什么?为什么即使 cout 被互斥锁锁定也不起作用!?

4

2 回答 2

2

问题在于 COUT 有一个隐含的取消点!

我们需要这样编码:

pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
    pthread_testcancel();
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

并在开头制作线程:

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

这确保只有 pthread_cancel() 有一个取消点......

于 2010-03-14T14:18:03.130 回答
1

尝试注释掉该行pthread_detach(thread_id);并运行它。您正在创建与 pthread_attr_t 分离的线程。

要么,要么尝试在 pthread_create 中传递 NULL 而不是 &attr (这样线程就不会被分离创建)并运行它。

我猜如果时机合适,当主线程尝试 pthread_detach 时,(已经分离的)线程就消失了,你将进入 pthread_detach 中的 Never Never Land。

编辑:

如果 cout 像 Gabriel 指出的那样有一个隐式取消点,那么很可能发生的情况是线程在持有互斥锁的同时取消(它永远不会在 cout 之后进入 pthreads_unlock_mutex),因此等待互斥锁的其他任何人都将被永远阻塞.

如果您需要担心的唯一资源是互斥锁,您可以跟踪您的线程是否将其锁定,然后在清理中解锁它,假设清理在同一个线程中运行。

看看这里,第 157 页:PThreads Primer

于 2010-03-14T06:00:01.603 回答