一、生产者 - 消费者模型
当多个线程同时操作一份共享数据时,我们会遇到一个非常现实的问题:有的线程负责生产数据,有的线程负责使用数据。如果数据还没准备好,使用端线程就不断去检查、争抢资源,会造成大量无意义的 CPU 消耗;而数据满了,生产端线程还继续写入,又会导致数据错乱。
我们可以用一个很形象的例子来理解:有一个只能容纳一个苹果的盘子,这就是我们的临界区;有一个人往盘子里放苹果,他是生产者;还有三个人从盘子里取苹果,他们是消费者。但关键在于:这几个人都被蒙上了眼睛,而且彼此之间无法交流。
于是就出现了尴尬的局面:生产者不知道盘子里有没有苹果,只能反复伸手去摸、去试探;消费者也不知道盘子里有没有苹果,只能不停过来查看、争抢。大家都在做无意义的尝试,既浪费精力,又可能出现'盘子空了还在取、盘子满了还在放'的混乱情况。

这就是典型的:缺少同步、缺少等待 - 通知机制。而我们要介绍的生产者 - 消费者模型,正是为了解决这个问题而生。
可以想到,出现这样的问题最大的原因就是多个线程之间缺少'配合',生产端放入了数据但是消费端不知道,消费端取走了数据但是生产端也不知道,盘子容量有限也引起了生产端和消费端内部的竞争,此时就引入了同步和等待 - 通知的核心思想,在上面的模型中,引入一把锁和一个铃铛。

锁的出现就防止了因为竞争产生的安全问题(多拿/多放),铃铛则解决了生产者和消费者之间的交流问题,让整个过程变得有序,消除无意义的访问,让过程更加高效。这整个过程中用到的锁和铃铛就是互斥锁和条件变量。
概括归纳:
总的来说,这个模型需要维护以下关系:
- 3 种关系:消费者与消费者之间互斥、消费者与生产者之间互斥、生产者与生产者之间互斥(多生产者)。
- 2 种角色:消费者与生产者。
- 1 个空间:消费者与生产者进行数据'交易'的空间。
二、条件变量
概念介绍
条件变量是一种用于多线程 / 多进程同步的机制,它允许线程在某个共享资源的状态不满足预设条件时,主动进入阻塞等待状态,直到其他线程修改了共享资源的状态并发出通知,才会被唤醒并重新检查条件。
相关接口

pthread_cond_wait:「死等」—— 只要没有其他线程发通知,线程会一直阻塞在条件变量上,直到被唤醒(或收到信号中断)。pthread_cond_timedwait:「限时等」—— 设定一个截止时间,若到时间仍未收到通知,函数会自动返回,线程被唤醒,避免'永久卡死'。
这里以 pthread_cond_wait 这个更为基础的接口展开:
接口原型包含两个形参:pthread_mutex_t * 和 pthread_cond_t *,为什么跟互斥锁也有关系呢?其实很容易想到,条件变量的初衷就是解决多线程对临界资源的处理问题,既然作为临界资源,必然需要互斥锁进行安全问题维护。
其中 pthread_cond_t 是条件变量对应的类型名称,其初始化和 pthread_mutex_t(互斥锁) 步骤相同。
需要配合 进行使用。






