浅谈linux - cond条件变量应用

概述

条件变量不是一个把锁,它实质上一个类似信号的东西,与锁相互配合使用,因为锁所能达到的功能就只有加锁和解锁,并不能实现线程之间的一些关联,于是条件变量就出现了,与锁相互配合使用。这与共享内存与信号量配合使用有些许相似之处。

注意

进程中有两个线程A和B,线程A由于某个条件不满足,阻塞等待条件为真,线程B执行的时候,使线程A等待的条件变为真。线程A继续执行,那么这个条件就是条件变量类型的一个变量。

另外,小编所有文章均是自己亲手编写验证,由于文件太多,小编就不在公众号后台一一回复列举了,若需要小编的工程代码,请关注公众号:不只会拍照的程序猿,后台回复需要的工程文件。小编看到后会第一时间回复。

接口

初始化条件变量

静态初始化

/**
 * @ 静态初始化一个条件变量
 */
 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

动态初始化

/**
 * @ 动态初始化一个条件变量
 * @ cond: 指定要初始化的条件变量的地址        cond_attr: NULL 默认值
 * @ 总是成功返回0
 */
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);

销毁条件变量

/**
 * @ 销毁条件变量,释放条件变量hold的资源
 * @ cond: 指定要销毁的条件变量的地址
 * @ 成功返回0,失败返回非0的错误码
 */
int pthread_cond_destroy(pthread_cond_t *cond);

启动等待线程

重启一个线程

/**
 * @ 从等待条件变量为真的线程中,重新启动一个线程,不确定哪一个.如果没有线程等待条件变量为真,什么都没发生
 * @ cond: 指定条件变量.在这个条件变量上等待的线程
 * @ 成功返回0,失败返回非0的错误码
 */
int pthread_cond_signal(pthread_cond_t *cond);

重启所有线程

/**
 * @ 重新启动等待条件变量为真的所有线程.如果没有线程阻塞,什么都不做
 * @ cond: 指定条件变量.在这个条件变量上等待的线程
 * @ 成功返回0,失败返回非0的错误码
 */
int pthread_cond_broadcast(pthread_cond_t *cond);

等待条件变量为真

阻塞等待

/**
 * @ 阻塞等待条件变为真
 * @ cond:指定条件变量        mutex: 指定锁的地址
 * @ 成功返回0,失败返回非0的错误码
 */
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

计时等待

/**
 * @ 计时等待条件变量为真
 * @ cond:条件变量        mutex: 指定锁的地址       abstime:计时时间
 * @ 成功返回0,失败返回非0的错误码
 */ 
int  pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

示例

★示例通过cond_test.c向用户展示条件变量的基本使用。

★包含演示程序cond_test.c(已验证通过)。

6dc85729c75f36ecfb0e3f3059ffd23b.png cond_test.c

/**
 * @Filename : cond_test.c
 * @Revision : $Revision: 1.00 $
 * @Author : Feng(更多编程相关的知识和源码见微信公众号:不只会拍照的程序猿,欢迎订阅)
 * @Description : 条件变量的基本应用示例
**/

#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>

/* 定义链表相关类型 */
struct node;
typedef struct node *list_t;

struct node {
    int data;
    struct node *next;
};

list_t head = NULL;    /* 链表初始化 */

/* 静态初始化锁 */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

/* 静态初始化一个条件变量 */
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;


/**
 * @ 生产者线程
 * @ args: 传递来的参数
 */ 
void *product(void *arg)
{
    struct node *tmp;

    while (1) {
        //生产一个新的节点
        tmp = (list_t)malloc(sizeof(struct node));
        tmp->data = rand()%1000+1;
        tmp->next = NULL;   
        printf("p:%d\n",tmp->data);

        pthread_mutex_lock(&mutex);        /* 加锁 */    
        /* 将新节点插入到链表的头部 */
        tmp->next = head;
        head = tmp;
        pthread_mutex_unlock(&mutex);    /* 解锁 */    

        pthread_cond_signal(&cond);        /* 发送条件变量 */
        sleep(rand()%5+1);
    }
}

/**
 * @ 消费者线程
 * @ args: 传递来的参数
 */
void *consume(void *arg)
{
    list_t tmp;

    while (1) {
        pthread_mutex_lock(&mutex);                /* 加锁 */    
        if (head == NULL)        
            pthread_cond_wait(&cond,&mutex);    /* 阻塞等待生产者生产//解锁 等待 重新获取锁 */      
        tmp = head;
        head = head->next;          
        pthread_mutex_unlock(&mutex);            /* 解锁 */    

        printf("c:%d\n",tmp->data);                /* 消费tmp */
        free(tmp);
        tmp = NULL;

        sleep(rand()%5+1);
    }
}

/**
 * @ 主函数,程序入口
 */
int main(void)
{
    pthread_t pid, cid;     /* 线程ID */

    srand(time(NULL));


    /* 创建线程 */
    if (pthread_create(&pid, NULL, product, "thread1") != 0) {
        printf("pthread1 create failed...\n");
        return -1;
    }

    if (pthread_create(&cid, NULL, consume, "thread2") != 0) {
        printf("pthread2 create failed...\n");
        return -1;
    }

    /* 阻塞等待线程的汇合,接收线程的退出状态码 */
    pthread_join(pid, NULL);
    pthread_join(cid, NULL);

    /* 销毁mutex锁 */
    pthread_mutex_destroy(&mutex);    
    /* 销毁条件变量 */
    pthread_cond_destroy(&cond);

    return 0;
}

验证

编译程序,记得加库-pthread

#编译代码,记得-pthread
ubuntu@U:~/study/cond$ gcc cond_test.c -pthread
ubuntu@U:~/study/cond$

执行程序

#执行代码
ubuntu@U:~/study/cond$ ./a.out 
p:99
c:99
p:417
c:417
^C
ubuntu@U:~/study/cond$

往期 · 推荐

实时系统vxWorks - 任务(重要)

实时系统vxWorks - 加载应用程序的方法

实时系统vxWorks - 在线调试

实时系统vxWorks - 虚拟机环境搭建

实时系统vxWorks - zynq7020移植vxWorks​​​​​​​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不只会拍照的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值