1

だから、私は4つのスレッドを同時に実行するクラスのプログラムを書いています。実行時に停止するという事実を除いて、プログラムは完全に機能しています。これがpthread_cond_waitの設定方法に関連しているのか、それとも他の何かに関連しているのかわかりません。プログラムを何度も手作業でたどっていますが、説明が見つかりません。
これが私のコードです:

#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <stdlib.h>

//#define TENP .1
//#define FIFTP .15

void *tenPercentA();
void *tenPercentB();
void *fiftPercentC();
void *fiftPercentD();

pthread_cond_t aPirate;
pthread_cond_t bPirate;
pthread_cond_t cPirate;
pthread_cond_t dPirate;
pthread_mutex_t mutex;
int pearls = 1000;

int main()
{
        pthread_t tid;

        pthread_setconcurrency(4);
        pthread_create(&tid, NULL, (void *(*)(void *))tenPercentA, NULL);
        pthread_create(&tid, NULL, (void *(*)(void *))tenPercentB, NULL);
        pthread_create(&tid, NULL, (void *(*)(void *))fiftPercentC, NULL);
        pthread_create(&tid, NULL, (void *(*)(void *))fiftPercentD, NULL);

        pthread_exit(0);
}

void *tenPercentA(){
        int totalA = 0;
        double tempA = 0;

        while(pearls > 0){
                pthread_mutex_lock(&mutex);
                if(pearls > 0){
                        tempA = pearls * .1;
                        tempA = ceil(tempA);
                        totalA = totalA + tempA;
                        pearls = pearls - tempA;
                        printf("Pirate A stole %1.1f pearls.\n", tempA);
                        printf("Pirate A's total: %d\n", totalA);
                        sleep(1);
                        pthread_cond_broadcast (&bPirate);
                        pthread_cond_broadcast (&cPirate);
                        pthread_cond_broadcast (&dPirate);
                        tempA = 0.0;
                }
                else{
                        printf("No more pearls!\n");
                        exit(0);
                }
                pthread_mutex_unlock(&mutex);
                pthread_cond_wait (&aPirate, &mutex);
        }
}

void *tenPercentB(){
        int totalB = 0;
        double tempB = 0;

        while(pearls > 0){
                pthread_mutex_lock(&mutex);
                if(pearls > 0){
                        tempB = pearls * .1;
                        tempB = ceil(tempB);
                        totalB = totalB + tempB;
                        pearls = pearls - tempB;
                        printf("Pirate B stole %1.1f pearls.\n", tempB);
                        printf("Pirate B's total: %d\n", totalB);
                        sleep(1);
                        pthread_cond_broadcast (&aPirate);
                        pthread_cond_broadcast (&cPirate);
                        pthread_cond_broadcast (&dPirate);
                        tempB = 0.0;
                }
                else{
                        printf("No more pearls!\n");
                        exit(0);
                }
                pthread_mutex_unlock(&mutex);
                pthread_cond_wait (&bPirate, &mutex);
        }
}


void *fiftPercentC(){
        int totalC = 0;
        double tempC = 0;

        while(pearls > 0){
                pthread_mutex_lock(&mutex);
                if(pearls > 0){
                        tempC = pearls * .15;
                        tempC = ceil(tempC);
                        totalC = totalC + tempC;
                        pearls = pearls - tempC;
                        printf("Pirate C stole %1.1f pearls.\n", tempC);
                        printf("Pirate C's total: %d\n", totalC);
                        sleep(1);
                        pthread_cond_broadcast (&bPirate);
                        pthread_cond_broadcast (&aPirate);
                        pthread_cond_broadcast (&dPirate);
                        tempC = 0.0;
                }
                else{
                        printf("No more pearls!\n");
                        exit(0);
                }
                pthread_mutex_unlock(&mutex);
                pthread_cond_wait (&cPirate, &mutex);
        }

}

void *fiftPercentD(){
        int totalD = 0;
        double tempD = 0;

        while(pearls > 0){
                pthread_mutex_lock(&mutex);
                if(pearls > 0){
                        tempD = pearls * .15;
                        tempD = ceil(tempD);
                        totalD = totalD + tempD;
                        pearls = pearls - tempD;
                        printf("Pirate D stole %1.1f pearls.\n", tempD);
                        printf("Pirate D's total: %d\n", totalD);
                        sleep(1);
                        pthread_cond_broadcast (&bPirate);
                        pthread_cond_broadcast (&cPirate);
                        pthread_cond_broadcast (&aPirate);
                        tempD = 0.0;
                }
                else{
                        printf("No more pearls!\n");
                        exit(0);
                }
                pthread_mutex_unlock(&mutex);
                pthread_cond_wait (&dPirate, &mutex);
        }

}

そして、実行時に実行する出力例を次に示します。

Pirate A stole 100.0 pearls.
Pirate A's total: 100
Pirate B stole 90.0 pearls.
Pirate B's total: 90
Pirate C stole 122.0 pearls.
Pirate C's total: 122

私が持っている唯一の考えは、CPUスケジューラーが2つのスレッドを連続して実行する準備ができているときに、プログラムがスタックしていることを説明している可能性があります。例:(スケジュールキュー内):A | B | C | C | D.何か提案はありますか?

4

2 に答える 2

1
 while(pearls > 0){
     pthread_mutex_lock(&mutex);
     if(pearls > 0){
          <do some stuff>

     } else {
           print "all done";
     }                
     pthread_mutex_unlock(&mutex);
     pthread_cond_wait (&bPirate, &mutex);
 }

したがって、すべての海賊がpthread_condition_waitで待機している場合、最後の海賊が最後の真珠を盗んだときに、真珠== 0であることわかり、ループを終了する可能性があります。これで、すべて完了した状態を印刷することはできません。そして、プログラムの最後から落ちて、何も印刷されずに終了します。

そのため、プログラムは停止し、何も印刷されません。

編集:(上記はまだ当てはまりますが、現時点で見ている問題ではありません)http://linux.die.net/man/3/pthread_cond_waitから:

それらは、呼び出し元のスレッドまたは未定義の動作の結果によってロックされたミューテックスで呼び出されるものとします。

これらの関数は、ミューテックスをアトミックに解放します

正常に戻ると、ミューテックスはロックされており、呼び出し元のスレッドが所有している必要があります。

So what you want is:
pthread_mutex_lock(&mutex);
while (pearls > 0) {
    <do your thing>
    <signal other threads>
    pthread_cond_wait(&mutex);
}
于 2012-11-09T06:26:17.313 に答える
0

プログラムには多くの問題があります。

1.-ロックなしのpthread_cond_wait:daveがすでに指摘したように、mutexをロックして呼び出す必要があります。そうしないと、未定義の動作が発生します(これは常に悪いことです)。

例:

pthread_mutex_lock(&mutex);
while (!conditionMet) {
  //..
  pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);

2.-ミューテックスで保護されていpearlsない変数へのアクセス:ミューテックス(で)でアクセスを保護せずに、スレッド内の変数にアクセスしていますwhile(pearls>0)。別のスレッドが書き込みを行っている可能性があります。アクセスはアトミックである可能性がありますが、保証されていません。

3.-スレッド内のexit(0)。exit()を使用すると、通常のプログラムが終了します。おそらく、これはスレッド関数内で必要なものではありません。returnスレッドを終了するために使用するだけです。

4.- pthread_exit(0); main()で。 pthread_exit()関数は、呼び出し元のスレッドを終了します。mainの最後で、すべてのスレッドが最初に終了するのを待つ必要があります。そのために使用します(スレッドごとにpthread_join1つ必要になります)。pthread_tその後、通常どおりに戻ってプログラムを終了します。

さらに検索する前に、まずこれらすべてを修正する必要があります。

于 2012-11-09T08:21:01.860 に答える