一,先上结论:
通过条件变量实现的阻塞,本质上依靠的是与条件变量相关联的互斥量,条件的检测是在互斥量的保护下进行的。当条件变量处于未触发的状态时,线程自动阻塞,并释放与条件变量相关联的互斥量。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,被唤醒的线程重新获得互斥锁,重新评价条件。
二,详细解释
1,初始化
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
2,锁定并等待条件发生
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);
pthread_cond_wait阻塞等待,pthread_cond_timedwait超时等待.
当pthread_cond_wait返回时,互斥量被自动锁住。
pthread_cond_wait函数的返回并不意味着条件的值一定发生了变化,也有可能是程序出问题,所以必须重新检查条件。pthread_cond_wait函数返回时,相应的互斥锁将被当前线程锁定,即使是函数出错返回。
阻塞在条件变量上的线程被唤醒以后,直到pthread_cond_wait()函数返回之前条件的值都有可能发生变化。所以函数返回以后,在锁定相应的互斥锁之前,必须重新测试条件值。最好的测试方法是循环调用pthread_cond_wait函数,并把满足条件的表达式置为循环的终止条件。如:通过while循环一直检查所等待的条件,当条件不成立时,进入pthread_cond_wait函数,此时由于条件尚未成立,所以阻塞。一直阻塞等待,直到某一线程修改条件状态为成立,并解锁等待时,pthread_cond_wait返回,此时重新判断等待条件是否成立,如果此时等待条件依旧成立,那么跳出while循环,进行业务处理。
pthread_mutex_lock();
while (condition_is_false)
{
pthread_cond_wait(cond_variable, mutex_variable);
}
...
业务处理
...
pthread_mutex_unlock();
阻塞在同一个条件变量上的不同线程被释放的次序是不一定的。
3,被解锁
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
这两个函数用于通知线程条件已经满足。调用这两个函数,向通过pthread_cond_wait函数等待条件的线程发送信号。需要注意, 一定要在等待条件改变之后,再调用函数发送信号。