线程同步之条件变量

条件变量不是锁(名字上就没有锁字。。。),但可以造成线程阻塞,通常与互斥锁配合使用。

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);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值