线程中的条件变量pthread_cond_t

一、条件变量概述

与互斥锁不同,条件变量是用来等待而不是用来上锁的,条件变量本身不是锁
条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。
条件变量的两个动作:
        ①. 条件不满, 阻塞线程
        ②. 当条件满足, 通知阻塞的线程开始工作
条件变量的类型: pthread_cond_t。

二、pthread_cond_init函数

1.函数原型

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);

2.功能

初始化一个条件变量

3.参数

        ①. cond:指向要初始化的条件变量指针。
        ②. attr:条件变量属性,通常为默认值,传NULL即可。

也可以使用静态初始化的方法,初始化条件变量:

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

4.返回值

      成功:0 ;         失败:非0错误

三、pthread_cond_destroy函数

1.函数原型

#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);

2.功能

        销毁一个条件变量

3.参数

        ①. cond:指向要初始化的条件变量指针。

4.返回值

      成功:0 ;         失败:非0错误

四、pthread_cond_wait函数

1.函数原型

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);

2.功能

阻塞等待一个条件变量
        ①. 阻塞等待条件变量cond(参1)满足
        ②. 释放已掌握的互斥锁(解锁互斥量)相当于pthread_mutex_unlock(&mutex);
            ①②两步为一个原子操作。
        ③. 当被唤醒,pthread_cond_wait函数返回时,解除阻塞并重新申请获取互斥锁pthread_mutex_lock(&mutex)。

3.参数

        ①. cond:指向要初始化的条件变量指针
        ②. mutex:互斥锁

4.返回值

      成功:0 ;         失败:非0错误

五、pthread_cond_timedwait函数(不常用)

1.函数原型

#include <pthread.h>
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);

2.功能

        用于条件变量等待,并允许设置超时时间。

3.参数

        ①. cond:要等待的条件变量。
        ②. mutex:与条件变量关联的互斥锁,调用前需已加锁。
        ③. abstime:绝对超时时间(从Epoch开始的秒和纳秒)。

struct timespec {
    time_t tv_sec;      /* seconds */ // 秒
    long   tv_nsec; /* nanosecondes*/ // 纳秒
}

4.返回值

      成功:0 ;         失败:非0错误

六、pthread_cond_signal函数

1.函数原型

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);

2.功能

        唤醒至少一个阻塞在条件变量上的线程。

3.参数

        ①. cond:指向要初始化的条件变量指针。

4.返回值

      成功:0 ;         失败:非0错误

七、pthread_cond_broadcast函数

1.函数原型

int pthread_cond_broadcast(pthread_cond_t *cond);

2.功能

        唤醒全部阻塞在条件变量上的线程

3.参数

        ①. cond:指向要初始化的条件变量指针。

4.返回值

      成功:0 ;         失败:非0错误

八、函数的示例

1.条件变量的示例

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
//互斥锁
pthread_mutex_t mutex;

//条件变量
pthread_cond_t cond;

int flag = 0;

//改变条件
void *fun1(void *arg)
{
        while(1){
                //加锁
                pthread_mutex_lock(&mutex);

                //改变变量
                flag = 1;

                //解锁
                pthread_mutex_unlock(&mutex);

                //发送信号
                pthread_cond_signal(&cond);
                sleep(1);
        }
        return NULL;
}

//等待条件
void *fun2(void *arg)
{
        while(1){
                //加锁
                pthread_mutex_lock(&mutex);

                if(flag == 0){
                        pthread_cond_wait(&cond, &mutex);
                }
                printf("条件为真,线程2执行...\n");

                flag = 0;
                //解锁
                pthread_mutex_unlock(&mutex);
        }
    return NULL;
}

int main()
{
        int ret;
        pthread_t tid1, tid2;

        //初始化互斥锁
        ret = pthread_mutex_init(&mutex, NULL);
        if(ret != 0){
                printf("pthread_mutex_init failed...\n");
                return 1;
        }

        //初始化条件变量
        ret = pthread_cond_init(&cond, NULL);
        if(ret != 0){
                printf("pthread_cond_init failed...\n");
        return 1;
        }

        pthread_create(&tid1, NULL, fun1, NULL);
        pthread_create(&tid2, NULL, fun2, NULL);

        //回收线程
        ret = pthread_join(tid1, NULL);
        if(ret != 0){
                printf("pthread_join tid1 failed...\n");
                return 1;
        }

        ret = pthread_join(tid2, NULL);
    if(ret != 0){
        printf("pthread_join tid2 failed...\n");
        return 1;
    }

        //回收互斥锁
        pthread_mutex_destroy(&mutex);

        //回收条件变量
        pthread_cond_destroy(&cond);

        return 0;
}

2.生产者与消费者条件变量模型

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex;
pthread_cond_t cond;

typedef struct _node_t{
        int data;
        struct _node_t *next;
}node_t;

node_t *head = NULL;

void *producer(void *arg)
{
        while(1){
                pthread_mutex_lock(&mutex);
                node_t *new = malloc(sizeof(node_t));
                if(new == NULL){
                        printf("malloc failed...\n");
                        break;
                }
                memset(new, 0, sizeof(node_t));

                new->data = random()%100 + 1;
                new->next = NULL;

                printf("生产者生产%d\n", new->data);
                //头插
                new->next = head;
                head = new;

                pthread_mutex_unlock(&mutex);
                pthread_cond_signal(&cond);

                sleep(random()%3+1);
        }
        pthread_exit(NULL);
}

void *customer(void *arg)
{
        node_t *tmp = NULL;
        while(1){
                pthread_mutex_lock(&mutex);
                if(head == NULL){
                        printf("没有消费任务......\n");
                        pthread_cond_wait(&cond, &mutex);
                }else{
                        tmp = head;
                        head = head->next;

                        printf("消费者消费%d\n", tmp->data);
                        free(tmp);
                }
                pthread_mutex_unlock(&mutex);
                sleep(random()%3+1);
        }
        pthread_exit(NULL);
}

int main(){
        pthread_t tid1 = -1, tid2 = -1;
        int ret = -1;

        srandom(getpid());
        ret = pthread_mutex_init(&mutex, NULL);
        if(ret != 0){
                printf("pthread_mutex_init failed...\n");
                return 0;
        }

        ret = pthread_cond_init(&cond, NULL);
    if(ret != 0){
        printf("pthread_cond_init failed...\n");
        return 0;
    }

        pthread_create(&tid1, NULL, producer, NULL);
        pthread_create(&tid2, NULL, customer, NULL);

        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);

        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值