条件变量概念
作用
条件变量的作用是用于多线程之间关于共享数据状态变化的通信。当一个动作需要另外一个动作完成时才能进行,即:当一个线程的行为依赖于另外一个线程对共享数据状态的改变时,这时候就可以使用条件变量。
他必须跟互斥锁一起配合使用,条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等待另一个线程发送信号来弥补互斥锁的不足,所以互斥锁和条件变量通常一起使用。
条件变量本身不是锁,但它也可以造成线程阻塞,通常与互斥锁配合使用,给多线程提供一个会合的场所。
相关函数
pthread_cond_init初始化
原型:
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
功能:
初始化一个条件变量
参数:
cond:条件变量
attr:条件变量属性,通常传NULL,表示使用默认属性
返回:
成功:0
失败:error(错误号码)
pthread_cond_wait等待条件变量满足
原型:
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
功能:
阻塞等待一个条件变量(等待唤醒)并解除相应的锁资源
参数:
cond:条件变量
mutex:互斥锁
返回:
成功:0
失败:error(错误号码)
注意:
被唤醒,pthread_cond_wait函数返回时,解除阻塞并重新申请获取互斥锁.
pthread_cond_broadcast唤醒全部在等待条件变量的线程
原型:
int pthread_cond_broadcast(pthread_cond_t *cond);
功能:
唤醒全部在等待条件变量的线程
参数:
cond:条件变量
返回:
成功:0
失败:error(错误号码)
pthread_cond_signal唤醒一个在等待条件变量的线程
原型:
int pthread_cond_signal(pthread_cond_t *cond);
功能:
唤醒一个在等待条件变量的线程(随机唤醒一个)
参数:
cond:条件变量
返回:
成功:0
失败:error(错误号码)
pthread_cond_destroy销毁条件变量
原型:
int pthread_cond_destroy(pthread_cond_t *cond);
功能:
销毁条件变量
参数:
cond:条件变量
返回:
成功:0
失败:error(错误号码)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
pthread_mutex_t mutex; //定义互斥锁
pthread_cond_t cond; //定义一个条件变量
int k ;
void *routine(void *arg);
void function(void *arg);
int main()
{
pthread_mutex_init(&mutex, NULL); //初始化互斥锁
pthread_cond_init(&cond,NULL); //初始化条件变量
pthread_t id[5];//定义一个线程ID号
for(int i = 0; i < 5; i++) //创建五个线程
{
pthread_create((id + i), NULL, routine, NULL);//创建线程线程id号保存地址
printf("创建了线程%ld\n",id[i]);
}
while(1) //循环上锁
{
pthread_mutex_lock(&mutex); //上锁
if(k == 0)
{
printf("请输入k的值:");
scanf("%d",&k);
}
pthread_cond_broadcast(&cond); //唤醒所有等待线程
pthread_mutex_unlock(&mutex);//解锁
sleep(1);
}
pthread_mutex_destroy(&mutex);//销毁互斥锁
pthread_exit(NULL);
}
//线程函数
void *routine(void *arg)
{
pthread_t id = pthread_self();
sleep(1);
while(1)
{
pthread_mutex_lock(&mutex);//上锁
pthread_cleanup_push(function,NULL); //函数压栈(线程清理函数)
if(k > 0) //条件满足就执行以下程序
{
printf("%ld我拿到资源了\n",id);
k--;
}
else
{
pthread_cond_wait(&cond,&mutex); //等待唤醒并解除相应的锁资源
}
pthread_mutex_unlock(&mutex); //解锁
pthread_cleanup_pop(0); //正常退出不执行线程清理函数
sleep(1);
}
return NULL;
}
//清理函数(防止死锁)
void function(void *arg)
{
printf("哟,咋了\n");
//解锁(防止线程异常结束尔造成的死锁)
pthread_mutex_unlock(&mutex);
}