1

乾杯、

論理的デッドロックを引き起こしているスレッドが 2 つあります => d_santa と d_patuljak (申し訳ありませんが、いくつかの部分はクロアチア語で書かれており、翻訳する時間がありませんでした)

d_santa はこれを行います

void d_santa(){ //dodati join!!!
    int j;
    pthread_mutex_lock(&m);
    while(1){
        pthread_cond_wait(&u_santa,&m);
        if ((br_sob==10)&&(br_patuljak)){
            printf ("Dajem poklone i rijesavam se sobova\n");
            pthread_cond_broadcast(&u_sob);
            sleep(2);
            for (j=2; j<=11; j++){
                printf ("Pokusavam brisat sob na %d\n",j);
                pthread_join(thred[j],NULL);
                br_sob--;
                printf ("broj sobova=%d\n",br_sob);
            }
        }
        if (br_sob==10){
            printf("Hrani nezahvalnu bagru\n");
            sleep(2);
        }
        if ((br_patuljak%3)==0){
            pthread_cond_broadcast(&u_patuljak);
            printf ("Rijesi problem patuljaka\n");
            sleep(1);               
            for (j=0; j<3; j++){
                br_ulaz++;
                printf("Oslobađam dretvu %d\n",H_ULAZ);
                pthread_join(thred[H_ULAZ],NULL);                                   
                br_patuljak--;
                }
        }
    }
    pthread_mutex_unlock(&m);
}

d_patuljak がこれを行います

void d_patuljak(){ //zavrsi implementaciju proizvodac potrosac
    pthread_mutex_lock(&m);
    br_patuljak++;
    printf ("Nastao je patuljak %d\n",br_patuljak);
    while(br_patuljak<3){
        pthread_cond_wait(&u_patuljak,&m);
    }
    printf ("Patuljak se oslobodio\n");
    if (br_patuljak==3){
        pthread_cond_signal(&u_santa);
    }
    pthread_mutex_unlock(&m);
}

それが役立つ場合は、ここにもd_sobがあります

void d_sob(){  //dobar
    int id; 
    pthread_mutex_lock(&m);
    id=br_sob+2;    
    br_sob++;
    printf ("Nastao je sob %d\n",br_sob);
    while(br_sob<10){
        pthread_cond_wait(&u_sob,&m);
    }
    pthread_cond_signal(&u_santa);
    printf ("Sob ceka slobodu %d, a za analizu br_sob=%d\n",id,br_sob); 
    pthread_mutex_unlock(&m);
}

タスク: d_santa は 1 回だけ作成され、d_patuljak が作成され続けている間、常に眠っているか、何か「役立つ」ことを行っています。グループ 3 が作成されると、santa がすべての問題を解決するのを助けることができるように (d_patuljak が速く作成されたかどうかに注意してください) 3 つ以上のパトゥリャクが存在する可能性がありますが、サンタは 3 つのグループしか取りません!!)。すすり泣きの場合と同様に、10 個になるまで作成され続け、その後はブロードキャストできます (11 個はあり得ません)。

私の解決策 (考え): 1、2、3 個のパトゥルジャクを作成し、それぞれが配列内に独自の場所を持っているようにします。Patuljak 3 が作成されると、彼はサンタを目覚めさせます (pthread_cond_wait もバイパスします)! サンタは目を覚まし、3 つの連続した pthread_cond_signals を呼び出して、patuljak 1、patuljak 2、patuljak 3 を解放します => 注: patuljak 1 は解放されてスレッドを終了し、pthread_cond_signal のすぐ下に配置した pthread_join によって「破棄」されます!!

問題: pthread_join(patuljak 1) が patuljak 1 を待ち続けるということは、pthread_cond_signal が patuljak 1 (おそらく patuljak 2 または 3) を解放できなかったことを意味します。この問題を解決する方法がわかりません。何をリリースするか、または patuljak 1,2,3 を正確にリリースする方法を知る方法はありますか? 私はブロードキャストを使用しますが、patuljak 4 はリリースされず、サンタは 3 つのグループのみを取得することはできません。

とにかく、プログラムはこれよりもはるかに大きいです。レインディア (=sob) にも同様の問題があり、ブロードキャストしようとしましたが、pthread_join でスタックします。patuljaks の問題が解決されれば、同じことが続くと感じています。トナカイ (patuljak=>dwarf) xd.

4

3 に答える 3

2

この種の問題は、次の 2 つのルールで解決できます。

  1. 条件変数を待機している可能性のあるスレッドが、実行する必要があることを実行できる場合pthread_cond_signalにのみ呼び出します。それ以外の場合は、常に を呼び出します。疑わしい場合は、いつでも安全ですので、お電話ください。pthread_cond_broadcastpthread_cond_broadcast

  2. 偽のウェイクアップが発生した場合に再度pthread_cond_wait呼び出すループ内で常に呼び出します。pthread_cond_wait「余分な」ウェイクアップが無害であり、スレッドが「すべきではない」ときにウェイクアップした場合にスレッドがスリープに戻るように、コードを設計する必要があります。

于 2013-12-08T19:54:52.843 に答える
0

どのスレッドが解放されたかを知りたい場合、簡単な方法は区別するためにスレッド ID を出力することです。Pthread の作成と終了を参照してください。

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   printf("Hello World! It's me, thread #%ld!\n", tid);
   pthread_exit(NULL);
}


int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0; t<NUM_THREADS; t++){
      printf("In main: creating thread %ld\n", t);
      rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }

   /* Last thing that main() should do */
   pthread_exit(NULL);
}

したがって、スレッド関数を次のように変更できます

void d_santa(void *threadid) {
}
于 2013-12-09T02:33:37.707 に答える