条件变量(cond):
为什么需要条件变量?
- 当一个线程互斥的访问某个变量时,它可能发现在其他线程改变该变量状态之前,它什么也做不了!(此时就是死锁,一种僵死状态)
我们需要一种机制,当互斥量锁住以后,当前线程还是无法完成自己的操作,那么就应该释放互斥量,让其他线程继续工作。
1. 可以用轮询机制,不停的查询你需要的条件;
2. 用条件变量机制;
条件变量函数:
(1)初始化
函数初始化
int pthread_cond_init(pthread_cond_t *restrict cont,const pthread_condattr_t *restrict attr);
参数:跟互斥量相似
cond: 要初始化的条件变量;
attr: 条件变量属性,一般设为NULL;
当然也可以用宏 : PTHREAD_CONT_INITALIZER 静态初始化
pthread_cond_t cond = PTHREAD_CONT_INITALIZER;
(2)等待条件满足
//非阻塞,
int pthread_cond_timedwite(pthread_conda_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);
//阻塞
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
参数:
cond: 要在这个条件变量上等待;
mutex: 互斥量
abstime: 指定等待时间,如果在规定时间没有通知,返回 ETIMEDOUT错误;
pthread_cond_wait()做的三件事:
1,释放锁—->2,等待锁—->3,收到条件信息,尝试获取锁
(3)唤醒等待
//唤醒改条件变量上的所有线程
int pthread_cond_broadcast(pthread_cond_t *cond);
//至少唤醒一个等待的线程
int pthread_cond_signal(pthread_cond_t *cond);
(4)销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
例子:
有全局变量money;主线程减小money,当money等于0时,子线程使money加上200;
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
pthread_cond_t cond; //定义条件变量
pthread_mutex_t mutex; //定义互斥量
int money; //定义全局资源
//线程函数
void* pthread_func(void* arg)
{
while(1)
{
pthread_mutex_lock(&mutex); //上锁
while(money>0)
{
printf("让子线程等待money等于0\n");
pthread_cond_wait(&cond,&mutex); //等待(阻塞)
}
//让子线程进入临界区查看
if(money==0)
{
money += 200;
printf("子线程money=%d\n",money);
}
//解锁
pthread_mutex_unlock(&mutex);
sleep(1);
}
return NULL;
}
int main()
{
pthread_t tid;
pthread_mutex_init(&mutex,NULL); //初始化互斥量
pthread_cond_init(&cond,NULL); //初始化条件变量
pthread_create(&tid,NULL,pthread_func,NULL);//创建子线程
money=1000;
while(1)
{
//上锁
pthread_mutex_lock(&mutex);
if(money>0)
{
money-=100;
printf("主线程:money=%d\n",money);
}
//解锁
pthread_mutex_unlock(&mutex);
//如果money=0就通知子线程
if(money==0)
{
printf("通知子线程>:\n");
pthread_cond_signal(&cond); //唤醒
}
sleep(1);
}
return 0;
}
结果: