如何知道pthread_cond_signal发布了哪个线程

时间:2013-12-08 19:50:38

标签: c multithreading pthread-join

干杯,

我有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只创建一次并且始终保持睡眠状态或做一些“有用”的事情,同时d_patuljak一直在创建,当创建一个组3时,他们唤醒圣诞老人,这样他就可以帮助他们解决所有问题(请注意,如果快速创建d_patuljak,可以有超过3 patuljaks但圣诞老人只有一组3 !!)。 狡猾的他们一直在创作,直到他们达到10后,他们可以被广播(不能有11个)

我的解决方案(想法): 我将创建1,2,3 patuljaks,每个patuljaks在一个数组中有自己的位置。 当patuljak 3被创建时,他将唤醒圣诞老人(也绕过pthread_cond_wait)! 圣诞老人将醒来并连续3次呼叫pthread_cond_signals以释放patuljak 1,patuljak 2然后patuljak 3 =&gt;注意:patuljak 1被释放以结束他的线程然后由pthread_join“摧毁”,我放在pthread_cond_signal下面!!

问题: pthread_join(patuljak 1)一直在等待patuljak 1,这意味着pthread_cond_signal无法释放patuljak 1(也许是patuljak 2或3)?我不知道解决这个问题的方法有没有办法知道将要发布什么或者如何释放完全patuljak 1,2,3?我会使用广播,但我不能patuljak 4将被释放,圣诞老人应该只采取3组。 编辑:我用pthread_cond_broadcast切换了pthread_cond_signal for patuljaks问题没有消失。

无论如何,这个程序比我大得多,我有一个类似的问题,我可以尝试播放raindeers(= sob),但是他们也被困在pthread_join,我有一种感觉,如果patuljaks的问题解决了同样的问题将跟随raindeers(patuljak =&gt; dwarf)xd。

3 个答案:

答案 0 :(得分:2)

两条规则将解决这些问题:

  1. 只有当任何可能正在等待条件变量的线程可以执行任何需要完成的操作时,才调用pthread_cond_signal。否则,始终调用pthread_cond_broadcast。如有疑问,请致电pthread_cond_broadcast,因为它始终是安全的。

  2. 在虚假唤醒的情况下,始终在一个循环中调用pthread_cond_wait,再次调用pthread_cond_wait。你必须设计你的代码,以便“额外的”唤醒是无害的,如果他们“不应该”醒来,线程就会重新入睡。

答案 1 :(得分:0)

如果您想知道哪个线程已发布,一种简单的方法是打印线程ID以进行区分。请参阅Pthread Creation and Termination

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) {
}

答案 2 :(得分:0)

所以实际的解决方案(由大师jax)是:

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()中的条件,第一个线程将是空闲的,然后减少将锁定其他线程的计数器。