Linux之线程条件变量cond

2023-05-16

概念:条件变量不是锁,要和互斥量组合使用。条件变量就是生产者“生产”完成,消费者才能“使用”,如果没有“产品”,消费者就会被条件变量cond阻塞等待生产者“生产”。(生产者与消费者模型)

函数:

  • 1.超时等待
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
           pthread_mutex_t *restrict mutex,
           const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);

struct timespec{

           time_t tv_sec;  /*seconds*/秒

           long tv_nsec;  /*nanoseconds*/纳秒

}

tv_sec 绝对时间,填写的时候,例如time(NULL)+600,表示设置超时600s。

  • 2.条件变量阻塞等待
       int pthread_cond_wait(pthread_cond_t *restrict cond,
           pthread_mutex_t *restrict mutex);

先释放锁mutex;

阻塞在cond条件变量上。

  • 3.初始化一个条件变量
       int pthread_cond_init(pthread_cond_t *restrict cond,
           const pthread_condattr_t *restrict attr);
       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  • 4.销毁一个条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
  • 5.信号,唤醒至少一个阻塞在条件变量cond上的线程
int pthread_cond_signal(pthread_cond_t *cond);
  • 6.唤醒阻塞在条件变量cond上的全部线程
int pthread_cond_broadcast(pthread_cond_t *cond);

示例:创建两个线程,一个线程为生产者,两个线程为消费者。(生产者与消费者模型)

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

int beginnum = 1000;

//初始化互斥锁和条件变量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

//定义一个链表,用于存取数据
typedef struct _ProdInfo
{
    int num;
    struct _ProdInfo *next;
}ProdInfo;

ProdInfo *Head = NULL;

void *thr_producter(void *arg)
{
    //负责在链表中添加数据
    while (1)
    {
        ProdInfo * prod = malloc(sizeof(ProdInfo));
        prod->num = beginnum++;
        printf("----%s----self = %lu----%d\n",__FUNCTION__,pthread_self(),prod->num);
        pthread_mutex_lock(&mutex);
        //添加到链表
        prod->next = Head;
        Head = prod;
        pthread_mutex_unlock(&mutex);
        //发起通知
        pthread_cond_signal(&cond);

        sleep(rand()%2);
        //free(prod);  //重复释放内存会报错,用完在释放
    }
    
    return NULL;
}

void *thr_customer(void *arg)
{
    ProdInfo *prod = NULL;

    while (1)
    {
        //获取链表中的数据
        pthread_mutex_lock(&mutex);
        //if(Head = NULL)
        while (Head == NULL)
        {
            pthread_cond_wait(&cond,&mutex);  //在此之前必须加锁
        }

        prod = Head;
        Head = Head->next;
        printf("----%s----self = %lu----%d\n",__FUNCTION__,pthread_self(),prod->num);
        pthread_mutex_unlock(&mutex);
        sleep(rand()%4);
        free(prod);
    }
    
    return NULL;
}

int main()
{
    pthread_t tid[3];
    pthread_create(&tid[0],NULL,thr_producter,NULL);
    pthread_create(&tid[1],NULL,thr_customer,NULL);
    pthread_create(&tid[2],NULL,thr_customer,NULL);

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);
    pthread_join(tid[2],NULL);
    pthread_mutex_destroy(&mutex);
    pthread_mutex_destroy(&cond);

    return 0;
}

输出:

~$ gcc cond_product.c -lpthread

~$ ./a.out
----thr_producter----self = 140197865371392----1000
----thr_customer----self = 140197856978688----1000
----thr_producter----self = 140197865371392----1001
----thr_customer----self = 140197731759872----1001
----thr_producter----self = 140197865371392----1002
----thr_customer----self = 140197856978688----1002
----thr_producter----self = 140197865371392----1003
----thr_producter----self = 140197865371392----1004
----thr_producter----self = 140197865371392----1005
----thr_customer----self = 140197731759872----1005
----thr_producter----self = 140197865371392----1006
----thr_producter----self = 140197865371392----1007
----thr_customer----self = 140197856978688----1007
----thr_customer----self = 140197731759872----1006

 

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

Linux之线程条件变量cond 的相关文章

  • 在单个命令中使用前缀重命名文件夹中的所有文件

    重命名带有前缀的文件夹中的所有文件 Unix 假设一个文件夹有两个文件 a txt b pdf 那么它们都应该从一个命令重命名为 Unix a txt Unix b pdf 如果您的文件名包含没有空格并且你没有任何子目录 你可以使用一个简单
  • 在64位操作系统上以32位模式和64位模式编译ioctl函数的执行有什么不同?

    我有 64 位 Enterprise SuSE 11 我有一个应用程序 它打开 HIDRAW 设备并在其上操作 ioctl 函数以从该设备获取原始信息 如下所示 struct hidraw devinfo devinfo int fd op
  • Mono 和 WebRequest 速度 - 测试

    在 mono 4 6 2 linux 中 我注意到 wget 下载文件的速度与webclient DownloadString 所以我做了一个小测试来调查 为什么 wget 明显比 C 快 根据我自己的实验 使用 wget 下载 手动读取文
  • 使用 sed 将 old-link-url 替换为 new-link-url

    我正在 bash 中编写一个脚本 将 old link url 替换为 new link url 我的问题是 sed 由于斜杠而无法替换 url 如果我只输入一些文字就可以了 my code sed e s old link new lin
  • 变量作为 bash 数组索引?

    bin bash set x array counter 0 array value 1 array 0 0 0 for number in array do array array counter array value array co
  • 如何使用 bash 脚本关闭所有终端,在每个终端中有效地按 Ctrl+Shift+Q

    我经常打开许多终端 其中一些正在运行重要的进程 例如服务器 而另一些则没有运行任何东西并且可以关闭 如果您按 重要 则会弹出确认提示Cntrl Shift Q在其中 如下所示 我想要一个 bash 脚本 它可以关闭所有终端 但将 重要 终端
  • 退出 bash 脚本但保持进程运行

    我正在运行服务器 需要使用参数执行以下命令 这些脚本目前工作得很好 但问题是当我运行脚本时我无法返回到控制台 它在控制台中保持运行 如果我强行停止它 那么该过程也会停止 我想继续运行该进程并返回到控制台 bin sh php home st
  • Docker DNS 设置

    我尝试使用自定义网络和 dos 设置创建 docker 容器 docker网络创建 driver bridge opt com docker network bridge enable ip masquerade true opt com
  • 在中断时获取 current->pid

    我正在Linux调度程序上写一些东西 我需要知道在我的中断到来之前哪个进程正在运行 当前的结构可用吗 如果我在中断处理程序中执行 current gt pid 我是否可以获得我中断的进程的 pid 你可以 current gt pid存在并
  • 如何阅读shell命令的源代码?

    我想阅读编写linux命令的实际源代码 我已经获得了一些使用它们的经验 现在我认为是时候与我的机器进行更深层次的交互了 我在这里找到了一些命令http directory fsf org wiki GNU http directory fs
  • UDP 广播发送失败:在 Linux 2.6.30 上“网络无法访问”

    我用udp广播写了一个程序 代码段如下 struct sockaddr in broadcast addr socklen t sock len sizeof broadcast addr bzero broadcast addr sock
  • gdb 错误 - 文件不是可执行格式:无法识别文件格式

    我正在尝试使用 gdb 调试某个名为 xdf 的程序 但是当我运行 gdb xdf 时 出现以下错误 home nealtitusthomas X ray astronomy heasoft 6 24 x86 64 pc linux gnu
  • 使用命令行将 MediaWiki 维基文本格式转换为 HTML

    我倾向于编写大量文档 因此 MediaWiki 格式对我来说很容易理解 而且比编写传统 HTML 节省了我很多时间 然而 我也写了一篇博客 发现一直从键盘切换到鼠标来输入正确的 HTML 标签会增加很多时间 我希望能够使用 Mediawik
  • 错误:NVIDIA-SMI 失败,因为无法与 NVIDIA 驱动程序通信

    NVIDIA SMI 抛出此错误 NVIDIA SMI 失败 因为无法与 NVIDIA 通信 司机 确保安装了最新的 NVIDIA 驱动程序并且 跑步 我清除了 NVIDIA 并按照提到的步骤重新安装了它here https askubun
  • 无关的库链接

    我有一个可能有点愚蠢的问题 因为我很确定我可能已经知道答案了 假设你有静态库A 动态共享库B和你的linux下的程序C 假设库 A 调用库 B 中的函数 并且您的程序调用库 A 中的函数 现在假设 C 在 A 中调用的所有函数都不使用 B
  • 是否从页面缓存中的脏页面进行文件读取?

    当字节写入文件时 内核不会立即将这些字节写入磁盘 而是将这些字节存储在页缓存中的脏页中 回写缓存 问题是 如果在脏页刷新到磁盘之前发出文件读取 则将从缓存中的脏页提供字节 还是首先将脏页刷新到磁盘 然后进行磁盘读取以提供字节 将它们存储在进
  • 如何从类似于 eclipse 的命令行创建可运行的 jar 文件

    我知道 eclipse 会生成一个可运行的 jar 文件 其中提取并包含在该 jar 文件中的所有库 jar 文件 从命令提示符手动创建 jar 文件时如何执行类似的操作 我需要将所有 lib jar 解压到类文件夹中吗 目前我正在使用 j
  • 确保 config.h 包含一次

    我有一个库项目 正在使用 Linux 中的 autotools 套件移植到该项目 我对自动工具很陌生 本周 我已经了解了其操作的基础知识 我有一个关于如何保留内容的问题config h免遭重新定义 我惊讶地发现生成的config h文件也没
  • CentOS目录结构是树形的吗?

    CentOS 上有相当于树的东西吗 如果你的 Centos 系统上没有安装 tree 无论如何我通常建议服务器设置使用最小安装磁盘 你应该在命令行中输入以下内容 yum install tree y 如果没有安装 那是因为您没有正确的存储库
  • 无法仅在控制台中启动 androidstudio

    你好 我的问题是下一个 我下载了Android Studio如果我去 路径 android studio bin 我执行studio sh 我收到以下错误 No JDK found Please validate either STUDIO

随机推荐

  • Linux设备驱动

    Linux设备驱动 介绍 Linux系列文章记录自己学习Linux开发的历程 最近终于把迅为4412开发环境搞定了 xff0c 先吐槽一波迅为 xff0c 版本太 的多了 xff0c 安卓Linux搞在一起 xff0c 还有那个硬件原理图
  • Linux 磁盘坏块修复处理(错误:read error: Input/output error)

    当磁盘出现坏块时 xff0c 你对所关联的文件进行读取时 xff0c 一般会出现 read error Input output error 这样的错误 反过来讲 xff0c 当你看到 read error Input output err
  • docker给运行中的容器添加端口映射

    问题描述 docker上面运行容器 xff0c run p 的时候只映射了一个端口 xff0c 后面对该nginx做扩展 xff0c 需要开放其他端口 当然重新再启一个容器在docker启动参数里多配置几个 p端口映射是能解决的 xff0c
  • Git常用命令符

    1 强制推送 xff08 慎用 xff0c 除非你认为其他冲突等可以丢弃 或者不是很重要 xff09 git push force 2 创建文件等小命令 touch a 创建一个a文件 echo 1234 gt gt a 把1234这个内容
  • 全网最全的 LeetCode 国人大神刷题指南,全部 Go 语言实现

    大家好 xff0c 我是欧盆索思 xff08 opensource xff09 xff0c 每天为你带来优秀的开源项目 xff01 说到 LeetCode xff0c 作为一个程序员来说 xff0c 应该不陌生 xff0c 近几年参加面试都
  • ROS实现串口通信

    虚拟串口的搭建 参考Linux下添加虚拟串口 xff0c 接收和发送数据 com py文件代码如下 xff1a span class token comment usr bin env python span span class toke
  • 基于Linux的UART驱动框架源码分析笔记

    文章目录 前言一 I MX6ULL串口接收和发送方式1 非DMA方式1 1 接收方式1 2 发送方式 2 DMA方式2 1 接收方式2 2 发送方式 二 UART驱动注册1 uart register driver 函数解析2 serial
  • cmake install 命令

    install指令用于定义安装规则 xff0c 安装的内容可以包括目标二进制 动态库 静态库以及文件 目录 脚本等 需要引入一个新的cmake指令和一个非常有用的变量 cmake install prefix 法一 xff1a cmake
  • 基于全景相机的视觉里程计算法研究

    一 视觉里程计 视觉里程计技术首先建立相机的成像模型 xff0c 接着通过标定算法计算相机参数 xff0c 最后建立相邻图像的关联并估计相机运动轨迹 1 1相机在空间中运动的描述 描述相机在三维空间中的运动状态 xff0c 即求解相机在空间
  • 多旋翼无人机组成(小白上路)

    1 无人机组成 1 1 机架 四旋翼最常见的两种机身布局如下图 xff1a 机架指无人机的承载平台 xff0c 通常用轴距衡量机架的大小 xff0c 轴距是指对角线两个螺旋桨的距离 xff0c 一般以mm为单位 xff0c 如F330表示轴
  • freertos创建任务后进入prvStartFirstTask发生HardFault_Handler中断

    在stm32f103zet6环境中移植成功freertos之后 xff0c 创建第一个任务之后 xff0c 会进入硬件中断 xff0c 经过排查发现死在了prvStartFirstTask 排查原因 xff1a 发现是启动文件startup
  • 解决无法对docker容器进行端口映射的问题

    初学docker的时候 xff0c 不知道为啥 xff0c 按着教程里打的代码 xff0c 最后却出现了映射失败的情况 即 xff1a 在docker内部设置的映射端口 xff0c 外部却没有办法访问 想了想 xff0c 不外乎两个原因 x
  • K8s手工创建kubeconfig

    我们通过 kubectl 命令行连接 k8s apiserver 时需要依赖 kubeconfig 文件 kubeconfig 文件通常包含了 context xff08 上下文 xff09 列表 xff0c 每个 context 又会引用
  • grep命令总结

    grep命令总结 1 关于 nbsp ps ef grep php grep v grep wc l grep v grep 代表在查询的最终结果中去掉grep命令本身 wc l 标示统计查询到的结果数量 grep常用命令 1 grep n
  • Ubuntu 16.04安装realsense D435i SDK以及realsense-ros

    先直接上一个报错信息 xff0c 折腾了半天才解决 在使用catkin make编译realsense ros时 xff0c 报错 traversing 4 packages in topological order realsense c
  • 关于视觉SLAM的一些常识(纯小白学习笔记)

    本文只是小白对于视觉slam的一个非常泛的介绍 xff0c 对于视觉slam中的数学运算均没有提及 xff0c 适合于对没有接触过视觉slam的新人进行一个简单的科普 作者即小白 xff0c 文章如有错误 xff0c 非常非常非常欢迎指正
  • 使用CubeMX快速搭建FREERTOS

    如何使用STM32快速搭建FREERTOS 小编之前一直使用正点原子家的产品 xff0c 最近准备学习学习TOUCHGFX 要用到HAL 43 RTOS 原子家的使用起来不方便 于是琢磨着使用STM32CUBEMX直接生成FREERTOS
  • 使用DMA+SPI驱动Aliyun Things 上的ST7789H2 LCD屏幕

    目录 前言硬件CUBEMX时钟树GPIOSPI 代码部分LCD驱动中断服务函数测试代码现象 前言 1 xff1a 驱动程序参考自https blog csdn net BearPi article details 104311705 2 x
  • SLAM测试5-YGZ-Stereo-Inertial(GAAS双目视觉ygz -立体惯性SLAM)

    这篇主要测试GAAS开源无人机里用到的一种SLAM算法 xff0c 目的是先对该SLAM算法进行熟悉 xff0c 再开始入手GAAS视觉定位 GIThub上的代码地址为 xff1a https github com gaoxiang12 y
  • Linux之线程条件变量cond

    概念 xff1a 条件变量不是锁 xff0c 要和互斥量组合使用 条件变量就是生产者 生产 完成 xff0c 消费者才能 使用 xff0c 如果没有 产品 xff0c 消费者就会被条件变量cond阻塞等待生产者 生产 xff08 生产者与消