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;
}

Coutをprintf()に置き換えると、最後まで「exit」で動作しますが、coutを使用すると(ロックされていても)、「detachingthread..。」を出力した後に実行可能ファイルがハングします。

プロから知るのはとてもクールだろう、ここでの問題は何ですか?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で&attrの代わりにNULLを渡して(スレッドがデタッチされて作成されないようにするため)、実行してみてください。

タイミングが正しければ、メインスレッドがpthread_detachを試行するまでに(すでにデタッチされている)スレッドがなくなり、pthread_detachでNeverNeverLandに入ると思います。

編集:

Gabrielが指摘するように、coutに暗黙のキャンセルポイントがある場合、おそらく何が起こるかは、ミューテックスを保持している間にスレッドがキャンセルされることです(coutの後にpthreads_unlock_mutexに到達することはありません)。したがって、ミューテックスを待機している他のユーザーは永久にブロックされます。 。

心配する必要がある唯一のリソースがミューテックスである場合、クリーンアップが同じスレッドで実行されると仮定して、スレッドがロックされているかどうかを追跡し、クリーンアップでロックを解除できます。

PThreadsPrimerの157ページをご覧ください。

于 2010-03-14T06:00:01.603 に答える