pthread_mutex_lock和pthread_cond_wait / signal导致死锁

时间:2017-03-06 14:27:13

标签: c multithreading mutex

我在程序中使用了2个线程,1个用于打印偶数,另一个用于按顺序打印奇数。当我运行下面的代码时,程序会在打印0和1后阻塞。看起来像死锁 但是如果我将rc = pthread_mutex_lock(& mutex)移动到PrintEvenNos()和PrintOddNos()中的while语句之上,则输出是顺序的并且是完整的(根据需要)。 有人可以解释为什么它在第一种情况下失败以及导致死锁的原因是什么?

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

pthread_t tid[2];
unsigned int shared_data = 0;
pthread_mutex_t mutex;
pthread_cond_t even,odd;
unsigned int rc;

void* PrintEvenNos(void*);
void* PrintOddNos(void*);

void main(void)
{
    pthread_create(&tid[0],0,&PrintEvenNos,0);

    pthread_create(&tid[1],0,&PrintOddNos,0);
    sleep(3);

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);
}

void* PrintEvenNos(void *ptr)
{
    //rc = pthread_mutex_lock(&mutex);     /*works when I uncomment here and comment the next mutex_lock */
      while (shared_data <= 5)
     {rc = pthread_mutex_lock(&mutex);
      if(shared_data%2 == 0)
       { printf("t1.....................................Even:%d\n",shared_data);
         shared_data++;
         pthread_cond_signal(&odd);
         rc=pthread_mutex_unlock(&mutex);
   }
     else
     {
           pthread_cond_wait(&even, &mutex);
     }
 }
  rc=pthread_mutex_unlock(&mutex);
}

void* PrintOddNos(void* ptr1)
{
// rc = pthread_mutex_lock(&mutex);   /*works when I uncomment here and comment the next mutex_lock */
   while (shared_data <= 5)
    {
     rc = pthread_mutex_lock(&mutex);
     if(shared_data%2 != 0)
        {
        printf("t2.....................................odd:%d\n",shared_data);
            shared_data++;
            pthread_cond_signal(&even);
            rc=pthread_mutex_unlock(&mutex);
        }
        else
            {
               pthread_cond_wait(&odd, &mutex);
        }
    }
 rc=pthread_mutex_unlock(&mutex);
}

2 个答案:

答案 0 :(得分:1)

您的程序有未定义的行为,因为您正在等待的线程在从pthread_cond_wait返回时重新获取锁定,然后再次在其已拥有的互斥锁上调用pthread_mutex_lock

您的评论意味着使用互斥锁。这正是pthread_cond_wait的作用:它在进入时释放锁定并在返回时重新获取它。

另外,从pthread_mutex_unlock分支中删除if,这是错误的。通常,您应该只有一对lock/unlock来电标记您的关键部分。

答案 1 :(得分:0)

按照评论中的说明移动锁定和解锁。如图所示,您的程序具有竞争条件,因此具有未定义的行为。在没有同步的情况下,您无法访问可能被另一个线程修改的数据,以阻止并发访问。