1

私はマルチスレッドが初めてなので、小さなプログラムから始めました。プログラムに期待される仕事は、1 つのスレッドが 1 つの数値を出力し、もう 1 つのスレッドが次の数値を出力し、定義された最大数までこのプロセスが続くように、2 つのスレッドを使用して整数を次々に出力することです。 .

このために、私は小さなプログラムを書きましたが、デッドロックに直面しています。gdb を使用してミューテックスの所有者を見つけようとしましたが、印刷ミューテックス コマンドを実行すると $3 = 2 と表示されます。

ソースコードは次のとおりです。

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

const int MAX_NUM = 13;

pthread_cond_t cond[1] = {PTHREAD_COND_INITIALIZER,};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int Count = 0;

using namespace std;

void* thread1(void*)
{
    do {
        cout<<"inside thread 1 abt to acquire lock"<<endl;
        // Increment counter in thread1
        pthread_mutex_lock(&mutex);
        cout<<"inside thread 1 blocked"<<endl;
        pthread_cond_wait(&cond[0],&mutex);
        cout<<"after pthread_cond_wait in thread1"<<endl;
        pthread_cond_signal(&cond[1]);
        if(Count < MAX_NUM)
        {
            Count++;
            pthread_mutex_unlock(&mutex);
            cout<<"Printing from thread 1"<<endl;
            cout<<Count<<endl;
        }
        else
        {
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }
    }while(1);
 }

 void* thread2(void*)
 {
     do{
         cout<<"inside thread 2 abt to acquire lock"<<endl;
         pthread_mutex_lock(&mutex);
         cout<<"inside thread 2 blocked"<<endl;
         pthread_cond_wait(&cond[1],&mutex);
         // Increment counter in thread2
         pthread_cond_signal(&cond[0]);
         if(Count < MAX_NUM)
         {
             Count++;
             pthread_mutex_unlock(&mutex);
             cout<<"Printing from thread 2"<<endl;
             cout<<Count<<endl;
         }
         else
         {
             pthread_mutex_unlock(&mutex);
             pthread_exit(NULL);
         }
    }while(1);
}

int main()
{
    pthread_t t[2];
    void* (*fun[2])(void*);
    fun[0]=thread1;
    fun[1]=thread2;

    for (int i =0 ; i < 2; ++i)
    {
        pthread_create(&t[i],NULL,fun[i],NULL);
    }
    cout<<"threads created"<<endl;

    pthread_cond_signal(&cond[0]);

    cout<<"In main after sending signal"<<endl;


    pthread_join(t[0],NULL);
    pthread_join(t[1],NULL);

    pthread_exit(NULL);
}

出力は次のとおりです。スレッド 1 内
でロックを取得する abt
スレッド 1 内でブロックさ
れた スレッド 2 内でロックを取得する abt スレッド 2内でブロックされた スレッド 作成された
スレッド 2 ブロックされたスレッド シグナルを送信した後、メインで


私は、main() スレッドがスレッド 1 にシグナルを送信し、スレッド 1 がその仕事 (つまり、カウンターの更新) を行い、シグナルをスレッド 2 に渡し、スレッド 2 がその仕事 (つまり、カウンターの更新) を行い、シグナルをスレッド 1 に渡すことを期待していました。最大数に達しました。最大数に達すると、各プロセスはミューテックスのロックを解除し、正常に終了します。

私を助けてください。私は本当に多くのことを試しましたが、何もうまくいきませんでした。

4

2 に答える 2

1

@TooTone の観察に加えて、条件変数がどのように機能するかの 1 つの側面を理解する必要があります。スレッドがブロックされていないときに条件変数を通知しても、何も起こりません。条件変数にはメモリがないため、少し後にスレッドがブロックされた場合、条件が再度通知されるまでロックされたままになります。

関数はスレッドを開始した直後に通知するため、スレッドがまだブロック ポイントに達していない可能性がありますmaincond[0]または、それらがブロックされている場合、あるスレッドが他のスレッドにシグナルを送信すると、他のスレッドがブロックされていないことが発生する可能性があります。したがって、条件変数配列を修正すると、テストがもう少し実行されることがわかりますが、最終的には再びデッドロックします。

条件変数を通知する前に遅延を導入するという簡単で汚いトリックを使用して、それを機能させることができました。これにより、シグナルが発生する前に、スレッドがブロッキング ポイントに到達する時間が与えられます。変更されたコードは次のとおりです。

const int MAX_NUM = 13;

pthread_cond_t cond[2] = {PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int Count = 0;

using namespace std;

void* thread1(void*)
{
    do {
        cout<<"inside thread 1 abt to acquire lock"<<endl;
        // Increment counter in thread1
        pthread_mutex_lock(&mutex);
        cout<<"inside thread 1 blocked"<<endl;
        pthread_cond_wait(&cond[0],&mutex);
        cout<<"after pthread_cond_wait in thread1"<<endl;
        if(Count < MAX_NUM)
        {
            Count++;
            pthread_mutex_unlock(&mutex);
            cout<<"Printing from thread 1"<<endl;
            cout<<Count<<endl;
            usleep(1000000);
            pthread_cond_signal(&cond[1]);
        }
        else
        {
            pthread_mutex_unlock(&mutex);
            usleep(1000000);
            pthread_cond_signal(&cond[1]);
            pthread_exit(NULL);
        }
    }while(1);
 }

 void* thread2(void*)
 {
     do{
         cout<<"inside thread 2 abt to acquire lock"<<endl;
         pthread_mutex_lock(&mutex);
         cout<<"inside thread 2 blocked"<<endl;
         pthread_cond_wait(&cond[1],&mutex);
         // Increment counter in thread2
         if(Count < MAX_NUM)
         {
             Count++;
             pthread_mutex_unlock(&mutex);
             cout<<"Printing from thread 2"<<endl;
             cout<<Count<<endl;
             usleep(1000000);
             pthread_cond_signal(&cond[0]);
         }
         else
         {
             pthread_mutex_unlock(&mutex);
             usleep(1000000);
             pthread_cond_signal(&cond[0]);
             pthread_exit(NULL);
         }
    }while(1);
}

int main()
{
    pthread_t t[2];
    void* (*fun[2])(void*);
    fun[0]=thread1;
    fun[1]=thread2;

    for (int i =0 ; i < 2; ++i)
    {
        pthread_create(&t[i],NULL,fun[i],NULL);
    }
    cout<<"threads created"<<endl;
    usleep(1000000);
    pthread_cond_signal(&cond[0]);

    cout<<"In main after sending signal"<<endl;


    pthread_join(t[0],NULL);
    pthread_join(t[1],NULL);

    pthread_exit(NULL);
}

この種のものに条件変数を使用することは、最善の考えではありません。セマフォはメモリを持っており、信号が送信されたときに誰も待っていなくても信号の状態を記憶しているため、このタスクにより適しています。

于 2013-07-19T23:56:40.543 に答える