条件变量的数据类型:pthread_cond_t
配合的函数有:
1、pthread_cond_t结构的初始化、销毁函数
#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);
|
Both return: 0 if OK, error number on failure |
2、获取条件变量的函数
#include <pthread.h> int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);
|
Both return: 0 if OK, error number on failure |
3、唤醒在条件变量上阻塞的函
#include <pthread.h> int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond);
|
Both return: 0 if OK, error number on failure |
举例:
如果我们有一个不限制长度的队列,有多个线程向队列写入数据,有多个线程从队列读取数据。要求:1 同时只有一个线程操作对联。2如果队列没有数据,读取线程需要等待。3 写队列线程,写入数据后通知等待数据的线程。
我们可以用下面的代码实现:
队列使用的要点:
1、必须要用pthread_mutex_t保护队列
2、用条件变量实现,等待、通知的功能
3、条件等待的判断条件必须是while,防止spurious awaken.如get_msg函数中的红色部分。
在代码中,用蓝色注释,解释条件变量使用,发生的事情。
struct data_block * get_msg(struct message_queue *mq)
{
struct data_block *db = NULL;
pthread_mutex_lock(&mq->lock);//获取mq->lock锁 ,保护下面队列为空的判断
while(mb_empty(&mq->message_block))
pthread_cond_wait(&mq->cond , &mq->lock);//释放mq->lock锁,获取mq->cond条件,线程阻塞。当写队列的线程发送signal信号的时候,获取mq->lock锁,释放mq->cond。
db = mb_pop_front(&mq->message_block);
pthread_mutex_unlock(&mq->lock);//最后释放mq->lock锁
return db;
}
int put_msg(struct message_queue *mq , struct data_block *db)
{
pthread_mutex_lock(&mq->lock); //获取mq->lock锁 ,保护下面队列操作
int errn = mb_push_back(db , &mq->message_block); pthread_metex_unlock(&mq->lock); //最后释放mq->lock锁
pthread_cond_signal(&mq->cond);//通知阻塞在mq->cond的线程
return errn;
}