条件变量
作用: 用于实现线程间同步
条件变量通过提供线程等待,直到被唤醒的进程唤醒,从而实现线程同步;条件变量本身不具备条件判断功能;也就是意味着什么时候该等待,什么时候该唤醒等待的线程,都需要用户来控制;
流程 需要和互斥锁搭配使用, 用户对临界资源进行判断, 如果需要那么就要将其加入到等待队列上, (判断条件需要循环判断, 因为先被唤醒的可能不是该线程, 那么就可能发生错误), 不同的角色应该等待在不同的等待队列上
原理 当需要等待的时候, 将该线程放入到等待队列上直到被唤醒。(提高性能)
实现过程
1. 定义条件变量
变量类型: pthread_cond_t ;
2.条件变量的初始化
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
cond: 所定义的条件变量
attr: 锁的属性, 不设置属性可置为 NULL
3. 条件不满足, 线程需要等待
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
cond 这个线程改在那个条件变量上等待
mutex 这个条件变量是针对那个互斥锁的(因为条件变量中等待队列)
作用: 将该线程加入到该条件变量的等待队列上, 直到被唤醒
4. 条件满足, 换线条件变量等待队列上的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
broadcast : 唤醒cond条件变量上的所有线程
signal : 唤醒cond条件变量等待队列上的至少一个线程
销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond)
销毁这个以及初始化的条件变量
使用示例
创建4个生产者线程负责生产, 一个队列仓库, 仓库满了后生产者就不能继续往里面添加数据, 创建4个消费者线程, 如果仓库的库存为0, 那么就不能在里面去数据
代码如下:
#include <iostream>
#include <queue>
#include <pthread.h>
#include <stdio.h>
#define MAX_CAPACITY 5
using namespace std;
class Queue{
queue<int> _store;
int _capacity;
pthread_mutex_t mutexs;
pthread_cond_t cond_Preducer;
pthread_cond_t cond_Consumer;
public:
Queue(int capacity = MAX_CAPACITY)
:_capacity(capacity)
{
pthread_mutex_init(&mutexs, NULL);
pthread_cond_init(&cond_Consumer, NULL);
pthread_cond_init(&cond_Preducer, NULL);
}
~Queue()
{
pthread_mutex_destroy(&mutexs);
pthread_cond_destroy(&cond_Consumer);
pthread_cond_destroy(&cond_Preducer);
}
bool push(const int& data)
{
pthread_mutex_lock(&mutexs);
while(_capacity ==_store.size())
{
pthread_cond_signal(&cond_Consumer);
pthread_cond_wait(&cond_Preducer,&mutexs);
}
_store.push(data);
pthread_cond_signal(&cond_Consumer);
pthread_mutex_unlock(&mutexs);
return true;
}
bool pop(int& data)
{
pthread_mutex_lock(&mutexs);
while(_store.empty())
{
pthread_cond_wait(&cond_Consumer,&mutexs);
}
data = _store.front();
_store.pop();
pthread_cond_signal(&cond_Preducer);
pthread_mutex_unlock(&mutexs);
return true;
}
};
void* run_push(void* arg)
{
int i=0;
Queue* p = (Queue*)arg;
while(1)
{
p->push(i++);
printf("压入一个元素val: %d\n",i);
}
return NULL;
}
void* run_pop(void* arg)
{
Queue* p = (Queue*)arg;
int data;
while(1)
{
p->pop(data);
printf("获取到一个值val: %d\n", data);
}
return NULL;
}
int main()
{
pthread_t Consumer[4];
pthread_t Preducer[4];
Queue arr;
for(int i=0;i<4;i++)
{
pthread_create(&Consumer[i], NULL, run_pop,(void*)&arr);
}
for(int i=0;i<4;i++)
{
pthread_create(&Preducer[i], NULL, run_push,(void*)&arr);
}
for(int i=0;i<4;i++)
{
pthread_join(Consumer[i],NULL);
}
for(int i=0;i<4;i++)
{
pthread_join(Preducer[i],NULL);
}
return 0;
}
运行结果: