用条件变量实现生产者消费者死锁问题

功能描述:
生产者线程 每隔2秒生产出一批数据直到队列满。
消费者线程 一有数据立即从队列 取出所有数据

代码:


pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
//消费者线程
void consume()
{
    while (1)
    {
        
        pthread_mutex_lock(&qlock);
        while (q.size() == 0)        //等待条件变量
        {
            pthread_cond_wait(&qready,&qlock);
        }
        
        //此时队列不为空,直接消费数据
        while (q.size() > 0)
        {
            int topValue = q.front();
            q.pop();
            cout << "消费者消费数据 " << topValue << "剩余个数=" << q.size() << endl;
        }
        pthread_mutex_unlock(&qlock);

    }
}

//生产者线程--每隔n秒生产一批数据,然后及时通知消费者
void produce()
{
    static int count = 0;
    while (1)
    {
        sleep(2);
        pthread_mutex_lock(&qlock);
        while (q.size() < MAXSIZE)
        {
            int val = ((count++) % MAXSIZE) + 1;
            q.push(val);
            cout << "生产数据 " << val << ",剩余个数=" << q.size() << endl;
            pthread_cond_signal(&qready);
        }
        pthread_mutex_unlock(&qlock);
        
    }
}

Q1:输出如图
图片.png

按照我预想的,发出signal后,为什么不是如下这种输出呢?
生产数据1,剩余个数1
消费数据1,剩余个数0
生产数据2,剩余个数1
消费数据2,剩余个数0

Q2: 我如果不加锁,不也用条件变量,相关pthread代码都删除,好像也能正常运行。
这个意义何在,线程竞争具体在哪。

第一次发帖求问,谢谢各位~

阅读 2.8k
2 个回答

你一直拿着锁生产,消费者拿不到锁没法消费。直到都生产完了。

已经理解。 调用pthread_cond_signal 会唤醒 消费者线程, 消费者线程在pthread_cond_wait返回前会重新获取锁。发现锁还未被释放,所以重新投入睡眠,等待生产者的线程调用pthread_mutex_unlock.

补充一句: 这样唤醒又睡眠一般来说会有性能消耗。查资料获得,在LinuxThreads或者NPTL里面,就不会有这个问题,因为在Linux 线程中,有两个队列,分别是cond_wait队列和mutex_lock队列, cond_signal只是让线程从cond_wait队列移到mutex_lock队列,而不用返回到用户空间,不会有性能的损耗。 虽然没损耗,但是还是要有解锁之后才能继续

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题