与互斥锁配合使用,可以达到如下效果——完成某个条件以后,指定线程才会继续执行。
生产者与消费者模型程序举例:生产者生产商品,消费者消费商品,如果没有商品了,消费者就要阻塞,等待商品生产出来。
主要函数如下:(注意其中的restrict关键词是告知编译器,所有修改该指针所指向内容的操作全部都是基于(base on)该指针的,即不存在其它进行修改操作的途径;这样的后果是帮助编译器进行更好的代码优化,生成更有效率的汇编代码。)
int pthread_cond_init(pyhread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
//条件变量初始化,第二个参数一般为NULL
int pthread_cond_destroy(pyhread_cond_t *cond);//摧毁条件变量标志
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 abstime);
//在abstime时间内都会阻塞等待条件触发,但是时间到了,也没有触发条件,就会超时返回,解除阻塞。
int pthread_cond_signal(pthread_cond_t *cond); //发出条件信号,如果有等待的线程,可以接受
int pthread_cond_broadcast(pthread_cond_t *cond);//广播信号条件,所有的线程都会被唤醒
注意:这里重点理解一下pthread_cond_wait函数,它有两个入口参数,第一个很容易理解,就是条件变量的结构体,但是第二个是锁结构体,这个参数是为了告诉条件变量在阻塞等待时,应该释放哪个锁,然后解除条件变量时,应该加上哪个锁。
一般这个函数是在抢到锁以后再使用的,所以一般条件变量的使用流程是这样的:一个线程抢到了锁,但是线程需要满足一些条件才能继续运行,比如说消费者必须有产品才能消费,如果没有产品的情况下,就进入阻塞模式,并且把锁释放,留给其他线程去操作,等到某个其他线程,比如生产者生产了产品,并使用了pthread_cond_signal发出条件信号了,这个线程才解除阻塞,并且加锁以后继续运行。
都说需要锁和条件变量配合使用,为什么不能直接使用条件变量,是因为条件变量是线程的共享资源,也有可能发生线程的争抢情况。需要加锁实现线程安全。
#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
pthread_mutex_t mutex;//定义互斥锁变量
pthread_cond_t cond;//定义条件变量
struct list{
int value;
list* next;
};//创建一个链表作为商品
list *Head=NULL;
int num=0;
void *thr_product(void *arg)
{
while (1){
list *food= new list;
food->value=num++;
cout<<__FUNCTION__<<"---self="<<pthread_self()<<"---"<<food->value<<endl;
pthread_mutex_lock(&mutex);
food->next=Head;
Head=food;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);//解除在条件变量上的阻塞
sleep(rand()%4);
}
return NULL;
}
void *thr_customer(void *arg)
{
list *pro=NULL;
while (1){
pthread_mutex_lock(&mutex);
if (Head==NULL) pthread_cond_wait(&cond, &mutex);
//在条件变量上阻塞,并且这条语句一定要与互斥锁配合使用,要先加锁
pro=Head;
Head=Head->next;
cout<<__FUNCTION__<<"---self="<<pthread_self()<<"---"<<pro->value<<endl;
pthread_mutex_unlock(&mutex);
sleep(rand()%4);
delete pro;
}
return NULL;
}
int main()
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_t tid[2];
pthread_create(&tid[0], NULL, thr_product, NULL);
pthread_create(&tid[1], NULL, thr_customer, NULL);
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
结果如图所示: