再次看到Condition,第一感觉还是觉得它和Mutex的功能是一样的,没必要存在。心里这么想,其实自己也知道怎么可能多余呢?老老实实的再分析一下代码,这次一定要把理解出来的内容记下来!都怪平时写代码太少,用到Condition的情况更少,偶尔想用的时候又忘记怎么用,于是就算了。
拿一段Condition的使用代码,反复的揣摩对比。
void process_msg(void) { struct msg *mp; for (;;) { pthread_mutex_lock(&qlock); while (workq == NULL) pthread_cond_wait(&qready, &qlock); mp = workq; workq = mp->m_next; pthread_mutex_unlock(&qlock); /* now process the message mp */ } }
经过反复的揣摩,我觉得Condition就像我们在调试代码的时候设置的某种断点,它设计的意义在于两个或者多个线程之间相互协调,相互配合,每个线程都要扮演一个角色,或者是生产者,或者是消费者,不管是哪一种,至少是一种。mutex虽然也是用于多线程间,但它设计的重点是保护自己的操作不被其它线程影响。如果想用它来实现生产者角色与消费者角色的区别,我只能说太难了,就算你想成为生产者,消费者也不一定给你机会,你得先抢到锁才行,消费者明明没有东西消费还要与生产者抢锁,这样子效率极其底下。
而在Condition介入下情况比较好了,消费者发现没有东西消费,迅速让出锁,并在Condition上阻塞,生产者可以迅速的获取锁(与消费者抢锁的概率要底出很多,因为阻塞在Condition上的消费者线程不会再去抢锁,除非它再次被叫醒)。
另外一个问题,Condition为什么需要Mutex呢?Condition从pthread_cond_wait返回只能说明条件有变化,至于哪些有变化,有什么变化,是否适合自己,Condition无法描述,也不需要它描述,因为我们无法把所有情况全部列举出来。我们只能在具体的代码中自己检测。这个检测的过程需要是一个原子操作,mutex的作用就是要保证条件检测和部分必须操作的原子性。
pthread_cond_wait还有一点需要注意,它执行进去之后先检查条件是否满足,如果满足继续向下执行,否则释放mutex,阻塞在condition上,等被叫醒的时候去抢mutex,抢到进入保护代码,执行完释放mutex。