考虑以下这种情形:
目前有若干个消费者,一个生产者,现在流水线队列中已满,生产者在:
MutexLockGuard lock(m_mutex); while(isFull()) notFull.wait();
生产者在notFull.wait()中陷入阻塞。
此时某个消费者拿走了一个产品,并通过notFull.notify()通知生产者队列未满,可以生产。
生产者从wait中醒来,再次竞争锁。
但很不幸,这个锁再次被另外一个消费者获得。
一直持续这样的流程,生产者点太背,一直未获取到这个锁,直到最后一个消费者又先抢到了这个锁。
此时,根据队列的情况分为两种情况:
a).如果队列还未空,这个消费者从队列中拿走产品并释放锁后,生产者终于拿到了这个锁,并往流水线中增加产品。
b).如果队列未空,这个消费者在通过while,进去notEmpty.wait()。在notEmpty.wait()内部,首先释放这个锁,然后陷入阻塞,这时生产者才再度拿到这个锁。
pthread_cond_wait()函数内部的机制就是:
1)释放锁
2)陷入阻塞
3)被唤醒后去竞争这把锁
1)的存在保证了该线程在阻塞前释放临界区给其他线程去竞争,不然若带着锁陷入阻塞,则这个生产者将得不到锁而无法增加产品,也无法notify这个带锁的消费者,进而形成死锁。
条件变量的作用在于,当通过notify唤醒在wait中的线程时,只是代表该线程有资格去竞争这把锁,而不是直接让该线程进入临界区。这样因为条件变量的存在,陷入阻塞的线程只有在条件满足时才会出来竞争锁,而如果没有条件变量,则只能不断的通过轮询去竞争临界区的所有权,从而使cpu从无限的空转中解放出来,直到条件满足(如对消费者是流水线中有产品,对生产者是流水线已空)时才出来竞争锁。