条件变量不是锁(名字上就没有锁字。。。),但可以造成线程阻塞,通常与互斥锁配合使用。
1、条件变量
pthread_cond_t cond;
2、函数
以下函数返回值均是成功返回0,失败返回错误号
1)pthread_cond_init;//动态初始化,配合phtread_cond_destroy一起使用。
或者用pthread_cond_t cond = PTHREAD_COND_INITIALIZER;(这样就是静态初始化了。)
这样就不用phtread_cond_destroy了。
2)pthread_cond_destroy;
3)pthread_cond_wait
4)pthread_cond_timedwait
5)pthread_cond_signal
6)pthread_cond_broadcast
3、pthread_cond_wait函数分析:
1)函数原型
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
2)函数作用:
a.阻塞等待一个条件变量cond满足条件,即:满足条件执行,不满足阻塞。
b.释放已经掌握的互斥锁,即相当于phread_mutex_unlock(&mutex);a,b步骤为一个原子操作,即不能分开,同时完成。(所以,需调用此函数前,需要对mutex进行初始化和加锁,对cond进行初始化)//此处解锁的原因是要让资源发生变化
c.被唤醒,pthread_cond_wait函数返回前,解除阻塞,并重新申请获取互斥锁pthread_mutex_lock(&mutex);
(因为b中解锁了嘛,所以此处需要重新拿锁)
使用phtread_cond_signal函数或者phtread_cond_broadcast来唤醒:
phtread_cond_signal函数能够唤醒阻塞在条件变量上至少一个线程。
phtread_cond_broadcast函数能够唤醒所有阻塞在条件变量上的线程。
4、以生产者消费者模型举例:
typedef struct{
NODE *next;
int value;
}NODE;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIAlIIZER;
pthread_cond_t cond = PTHREAD_COND_INITIAlIIZER;
NODE* head = NULL;
NODE* p = NULL;
void* productor(void*arg)
{
while(1)
{
p = (NODE*)malloc(sizeof(NODE));//生产东西
p->value = rand()%100;
printf("productor data %d",p->value);
pthread_mutex_lock(&mutex);
p->next = head;//将生产的东西 挂在公共区域上
head = p;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);//将等待条件变量的线程唤醒
sleep(rand()%3);
}
}
void* consumer(void*arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
while(head == NULL)//头指针为空,即没有生产,所以要调用wait函数,会阻塞条件变量满足
{ //如果是单个消费者线程,此处可用if(会阻塞等待,不往下执行),多个消费者线程用while
pthread_cond_wait(&cond,&lock);
}
p = head;
head = p->next;
pthread_mutex_unlock(&mutex);
printf("consurmer%d\n",p->value);
free(p);
p= NULL;
sleep(rand()%3);
}
}
int main()
{
pthread pid,cid;
srand(time(NULL));
pthread_create(&pid,NULL,productor,NULL);
pthread_create(&cid,NULL,consumer,NULL);
pthread_join(pid,NULL);
pthread_join(cid,NULL);
return 0;
}
生产者:生产了共有资源(如上:链表中增加数据),调用pthread_cond_signal();来唤醒一个等待条件变量的线程;
消费者:消费共有资源(如上,链表中删除数据),首先调用pthread_cond_wait(),来等待条件变量,倘若生产者线程已经先执行,生产了数据,调用pthread_cond_signal(),消费者线程将不会阻塞直接拿锁往下进行;倘若消费者线程先执行了,数据还没有生产出来,消费者线程就会阻塞。
总结:
1)、消费者中的条件一直满足的时候,条件变量不发挥作用;
2)、条件变量的意义是使 消费者线程在条件不满足的时候,让线程处于阻塞态,消费者线程条件满足时会收到生产者的signal信号,取消阻塞,继续往下执行。
5、pthread_cond_timedwait(*,*,*)函数的使用//三个参数都是指针

pthread_cond_timedwait()函数有三个参数:
(1)pthread_cond_t cond:条件变量(触发条件)
(2)pthread_mutex_t mutex: 互斥锁
(3)struct timespec abstime: 等待时间(其值为系统时间 + 等待时间)绝对时间,
因为unix系统诞生于1969年末,故将1970年1月1日0点0分0秒当做unix系统的计时元年。

注意区分:
abstime绝对时间的算法:从linux元年开始算的1970/1/1/00:00:00
所以用的时候,从当前时间开始往后加时间
time_t cur= time(NULL);//获取当前时间
struct timespec t;
t.tv_sec = cur+10;//定时10s
pthread_cond_timedwait(&cond,&mutex,&t);

321

被折叠的 条评论
为什么被折叠?



