Как узнать, какая нить была освобождена pthread_cond_signal

Ура,

У меня есть 2 потока, вызывающие логический тупик => d_santa и d_patuljak (извините, некоторые произведения написаны на хорватском языке, и у меня не было времени на перевод)

это делает д_санта

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 создается только один раз и всегда остается спящим или делает что-то "полезное", в то время как d_patuljak продолжает создаваться, и когда создается группа 3, они пробуждают Санту, чтобы он мог помочь им решить все их проблемы (обратите внимание, если d_patuljak создается быстро может быть более 3-х патуляков, но Санта берет только 3 группы!!). Подобно рыданиям, они продолжают создаваться, пока не достигнут числа 10, после чего их можно будет транслировать (их не может быть 11)

Мое решение (мысли): я создам 1,2,3 патуляка, каждый из которых имеет свое местоположение в массиве. Когда патуляк 3 создан, он разбудит Санту (также обходя pthread_cond_wait)! Санта проснется и вызовет 3 последовательных вызова pthread_cond_signals, чтобы освободить patuljak 1, patuljak 2, затем patuljak 3 => note: patuljak 1 освобождается, чтобы закончить его поток, после чего он будет "уничтожен" pthread_join, который я поместил прямо под pthread_cond_signal!!

Проблема: pthread_join(patuljak 1) продолжает ждать patuljak 1, что означает, что pthread_cond_signal не удалось выпустить patuljak 1 (возможно, patuljak 2 или 3)? Я не знаю, как решить эту проблему, есть ли способ узнать, что будет выпущено, или, может быть, как выпустить именно патуляк 1,2,3? Я бы использовал трансляцию, но я не могу выпустить патуляк 4, а Санта должен брать только группы по 3. РЕДАКТИРОВАТЬ: я переключил pthread_cond_signal с pthread_cond_broadcast для patuljaks, проблема не исчезла.

В любом случае, программа намного больше, чем эта, у меня есть похожая проблема с дождевиками (= всхлип), которую я могу и пытался транслировать, но они также застряли в pthread_join, у меня такое чувство, что если проблема с патуляками решена, то будет следовать дождевые олени (патуляк => карлик) xd.

3 ответа

Решение

Два правила решат такие проблемы:

  1. Только звонок pthread_cond_signal когда любой поток, который может ожидать переменную условия, может делать все, что нужно, чтобы это сделать. В противном случае всегда звоните pthread_cond_broadcast, В случае сомнений звоните pthread_cond_broadcastкак всегда безопасно.

  2. Всегда звони pthread_cond_wait внутри цикла, который вызывает pthread_cond_wait снова в случае ложного пробуждения. Вы должны разработать свой код так, чтобы "лишние" пробуждения были безвредными, а потоки просто возвращались в спящий режим, если они просыпались, когда "не должны".

Если вы хотите узнать, какой поток выпущен, простой способ - распечатать идентификатор потока для различения. Обратитесь к 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) {
}

Таким образом, реальное решение (гроссмейстером Джексом) было:

d_patuljak

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

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++){
                varijabla2++;               
            }
            br_sob=br_sob-10;
        }
        if (br_sob==10){
            printf("Hrani nezahvalnu bagru\n");
            sleep(2);
        }
        if (br_patuljak>=3){
            printf ("Rijesi problem patuljaka\n");              
            sleep(1);
            for (j=0; j<3; j++){
                varijabla++;
                pthread_cond_signal(&u_patuljak);                                   
            }
            br_patuljak=br_patuljak-3;
        }
    }
    pthread_mutex_unlock(&m);
}

То же решение можно применить к d_sob .... короче говоря, проблема заключалась в условии while(), первый поток был бы свободен, а затем уменьшал счетчик, который блокировал бы другие потоки.

Другие вопросы по тегам