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 只创建一次,并且在 d_patuljak 不断创建时始终保持睡眠或做一些“有用”的事情,当创建第 3 组时,他们唤醒圣诞老人,以便他可以帮助他们解决所有问题(请注意,如果 d_patuljak 快速创建patuljaks 可以超过 3 个,但圣诞老人只需要 3 个一组!!)。与 sob 类似,它们会不断被创建,直到达到 10 个之后才能被广播(不能有 11 个)

我的解决方案(想法):我将创建 1,2,3 个 patuljak,每个 patuljak 在数组中都有自己的位置。创建 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 组。编辑:我将 pthread_cond_signal 与 pthread_cond_broadcast 切换为 patuljaks 问题并没有消失。

无论如何,该程序比这要大得多,我有一个与raindeers(= sob)类似的问题,我可以并尝试广播,但他们也卡在pthread_join,我有一种感觉,如果patuljaks的问题得到解决,同样会遵循雨鹿(patuljak=>矮人)xd。

4

3 回答 3

2

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

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

  2. 始终pthread_cond_wait在循环中调用,该循环pthread_cond_wait在发生虚假唤醒时再次调用。您必须设计您的代码,以便“额外”唤醒是无害的,并且如果线程在“不应该”时唤醒,它们只会重新进入睡眠状态。

于 2013-12-08T19:54:52.843 回答
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() 中的条件,第一个线程将是空闲的,然后减少会锁定其他线程的计数器。

于 2013-12-09T10:01:58.330 回答
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 回答