unix线程条件变量原理分析

此处摘录了unlix环境高级编程11.6.6一节的代码作为实例代码:

#include

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);
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);

}


条件变量本质上是一个全局可访问的flag,所以,线程在调用pthread_cond_wait之前必须先调用pthread_mutex_lock对条件变量加互斥锁。pthead_cond_wait函数首先检测当前条件变量的值,如果条件变量为真,线程直接从pthread_cond_wait函数返回,继续执行下面的代码。如果为假,那么线程不具备工作的条件,必须等待,为了不浪费CPU资源,pthread_cond_wait函数让线程进入了休眠状态。同时,为了不阻塞其他线程,让其他线程也可以访问条件变量,pthread_cond_wait函数又释放了互斥锁,但此时进入休眠状态的线程依然位于pthread_cond_wait函数内,执行过程在pthread_cond_wait函数处阻塞。
当线程工作的条件具备时,pthread_cond_signal函数负责将条件变量修改为真,同时发信号通知等待的线程。那么此时,因等待条件变量而进入休眠状态的线程将在pthread_cond_wait函数内被信号唤醒,线程被唤醒的同时重新获取了互斥锁,并再次对条件变量检测,发现条件变量为真,线程具备了工作的条件,至此,pthread_cond_wait函数从阻塞(线程休眠)状态返回,然后线程继续执行下面的代码。线程在完成对全局资源的访问后,释放互斥锁。

条件变量机制是将全局标记、线程信号、线程休眠、加锁解锁结合在了一起。主要内容包含在pthread_cond_wait函数内,包括:
1 检测条件变量,为真从函数返回,继续执行下一步,为假,则:
1.1 设置线程等待条件(变量变为真的)信号
1.2 让线程进入休眠状态
1.3 释放互斥锁
2 收到条件(变量变为真的)信号后,则:
2.1 唤醒休眠的线程
2.2 重新获取互斥锁
2.3 重新检测条件变量,为假,则继续执行步骤1,为真则从函数内返回。
pthread_cond_signal函数的主要工作是负责修改条件变量的值和发送信号提醒等待线程条件变量变成了真值。

互斥锁保护的是两种资源:条件变量和线程需要访问的全局资源。因为线程在pthread_cond_wait函数内被唤醒后,重新获取了互斥锁,然后才能检测条件变量,条件变量为真,从函数返回后,并没有申请获取其他的互斥锁,就继续对全局资源访问,并在完成访问后只释放了一次互斥锁。


你可能感兴趣的:(Unix环境编程原理探析)