条件变量是线程的另一种同步机制,它和互斥量是一起使用的。互斥量的目的就是为了加锁,而条件变量的结合,
使得线程能够以等待的状态来迎接特定的条件发生,而不需要频繁查询锁。
条件变量的使用需要条件变量和互斥量:
pthread_cond_t cond;
pthread_mutex_t mutex;
使用例子中,可看APUE上的一个例程:
#include <pthread.h>
struct msg {
struct msg *m_next;
/* ... more stuff here ... */
};
struct msg *workq;
pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
void
process_msg(void)
{
struct msg *mp;
for (;;) {
pthread_mutex_lock(&qlock);a
while (workq == NULL)
pthread_cond_wait(&qready, &qlock);
mp = workq;
workq = mp->m_next;
pthread_mutex_unlock(&qlock);
/* now process the message mp */
}
}
void
enqueue_msg(struct msg *mp)
{
pthread_mutex_lock(&qlock);
mp->m_next = workq;
workq = mp;
pthread_mutex_unlock(&qlock);
pthread_cond_signal(&qready); //通知等待线程条件状态改变
}
其中包括条件变量和互斥量的初始化,是必需的步骤。这一例程是对msg队列的一个处理。队列在加入消息后便可通知等待
的线程处理消息。首先在队列加入消息时是需要加锁的,加入消息后解锁。
重点关注消息处理函数,它在进入消息处理时加上了锁,然后调用pthread_cond_wait(&qready, &qlock) ,然后这个函数会
把调用线程放到等待条件的线程列表上,并对互斥量进行解锁,当线程被通知返回时,互斥量再次被锁住。(我就是在这里开始没弄明白)
另一个问题是,加入消息的函数中, 是先解锁,还是先发送通知消息。其实都可以,但都有一点问题:如果先通知了,那么
等待的线程运行之后就会阻塞住(因为锁还没解开)。如果先解锁了,那么在通知等待线程之前,这个线程可能会获得互斥锁,
使条件失效,那么再通知的时候,条件就没意义了,这时需要做一些检查,确保信息已存在,再执行处理。