浅谈linux - cond条件变量应用

2023-05-16

概述

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

注意

进程中有两个线程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​​​​​​​

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅谈linux - cond条件变量应用 的相关文章

随机推荐

  • 浅谈linux - 搭建nfs服务

    概述 本文用于展示如何搭建nfs服务 xff0c 实现开发机和目标机之间的文件共享 注意 开发环境 xff1a ubuntu 16 04 xff0c linux 4 9 xff0c 开发板 xff1a TLZ7x EasyEVM A3 另外
  • 听说Zynq-petalinux编译linux程序

    概述 PetaLinux 是一种嵌入式 Linux 软件开发套件 SDK 主要用于赛灵思 FPGA 基片上系统设计 注意 开发环境 linux4 9 VirtualBox 6 1 ubuntu 16 04 开发板 TLZ7x EasyEVM
  • 实时系统vxWorks - udp组播通讯

    概述 组播又称多目标广播 多播 网络中使用的一种传输方式 它允许把所发消息传送给所有可能目的地中的一个经过选择的子集 即向明确指出的多种地址输送信息 是一种在一个发送者和多个接收者之间进行通信的方法 注意 开发环境 vxWorks6 9 4
  • 实时系统vxWorks - tcp客户端通讯

    概述 传输控制协议 TCP Transmission Control Protocol 是一种面向连接的 可靠的 基于字节流的传输层通信协议 注意 开发环境 vxWorks6 9 4 workbench3 3 5 另外 小编所有文章均是自己
  • nvm导致React Native启动失败

    错误如下 xff1a The following build commands failed PhaseScriptExecution CP User Generate Specs Users qiaohao Library Develop
  • 实时系统vxWorks - tcp服务器通讯

    概述 接上一篇文章 本文主要展示vxWorks下TCP服务器的编程方法 注意 开发环境 vxWorks6 9 4 workbench3 3 5 另外 小编所有文章均是自己亲手编写验证 由于文件太多 小编就不在公众号后台一一回复列举了 若需要
  • 开发工具 - 离线安装VS code插件

    概述 VSCode具有丰富的插件库 xff0c 程序猿们可以根据自己需要安装插件 xff0c 大大提高VS code工具的生产力 注意 开发环境 xff1a Ubuntu 16 04 xff0c 开发板 xff1a TLZ7x EasyEV
  • 开发工具 - 设置vs code主题

    概述 不可否认 xff0c 良好的界面风格能给程序员带来更好的软件体验 对于小编这种颜值至上的人来说 xff0c 一个高颜值的软件会让人心情愉悦 xff0c 编写代码效率提高 这也是VS code和Source Insight软件的对比优势
  • 开发工具 - 设置vs code显示中文

    概述 本文主要针对像小编一样对于英文看着比较吃力的小伙伴 xff0c 如果你对自己英文很有信心 xff0c 那么建议忽略此文章 注意 开发环境 xff1a Ubuntu 16 04 xff0c 开发板 xff1a TLZ7x EasyEVM
  • 通信协议 - ntp时间同步

    概述 NTP Network Time Protocol xff09 网络时间协议基于UDP xff0c 用于网络时间同步的协议 xff0c 使网络中的计算机时钟同步到UTC xff0c 再配合各个时区的偏移调整就能实现精准同步对时功能 提
  • 通信协议 - ARINC615A加卸载协议

    概述 ARINC615A加卸载端系统由加载端软件和目标端软件组成 xff0c 通过加载端软件和目标端软件的通信共同完成端系统设备的数据加卸载功能 加载端软件运行于大容量设备中 xff0c 被加载端即目标端软件运行于AFDX交换机内和其他端系
  • 我用C语言玩对象,封装相似算法的策略模式

    概述 在策略模式 xff08 Strategy Pattern xff09 中 xff0c 一个类的行为或其算法可以在运行时更改 这种类型的设计模式属于行为型模式 在策略模式中 xff0c 我们创建表示各种策略的对象和一个行为随着策略对象改
  • 浅谈linux - 库文件制作与使用

    概述 本质上来说 xff0c 库文件就是可执行代码的二进制形式 xff0c 可以被操作系统载入内存中执行 Linux操作系统支持的函数库分为静态库和动态库 xff0c 动态库又称共享库 Linux系统有几个重要的目录存放相应的函数库 xff
  • 浅谈linux - vs code搭建运行调试环境

    概述 在Linux开发过程中 xff0c 用不惯vim的用户往往会选择vs code软件或者source insight软件编写相关的源代码 xff0c 由于vs code对linux系统的支持及界面的美观 xff0c 所以小编往往会选择使
  • 浅谈linux - samba实现linux与windows文件共享

    概述 Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件 xff0c 而SMB是Server Message Block的缩写 xff0c 即为服务器消息块 xff0c SMB主要是作为Microsoft的网络通讯协
  • mysql的update、delete、和insert into时表别名用法

    mysql数据库update delete 和insert into表的时候 xff0c 如果要使用表别名 xff0c 必须按照规范写法来写 xff1a insert xff1a 简写 xff1a insert into t a a a i
  • 浅谈linux - RT Linux解决方案

    概述 RT Linux Real Time Linux 亦称作实时 Linux xff0c 是 Linux 中的一种硬实时操作系统 xff0c 它最早由美国墨西哥理工学院的 V Yodaiken 开发 产品资料提供的 Linux RT 内核
  • 浅谈linux - 线程的基本应用

    概述 线程 xff08 英语 xff1a thread xff09 是操作系统能够进行运算调度的最小单位 它被包含在进程之中 xff0c 是进程中的实际运作单位 注意 线程和进程之间的区别 1 线程是执行的基本单位 xff1b 进程是资源分
  • 浅谈linux - mutex锁应用

    概述 互斥锁是专门用于处理线程之间互斥关系的一种方式 xff0c 它有两种状态 xff1a 上锁状态 解锁状态 如果互斥锁处于上锁状态 xff0c 那么再上锁就会阻塞到这把锁解开为止 xff0c 才能上锁 解锁状态下依然可以解锁 xff0c
  • 浅谈linux - cond条件变量应用

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