当前位置: 首页 > news >正文

linux-线程条件变量(cond)

概述

        与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用
        条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:
        1.一个线程等待"条件变量的条件成立"而挂起;
        2.另一个线程使 “条件成立”(给出条件成立信号)
        想象一种情况,我创建一个线程去执行下雨收衣服的工作,但是大多数时候天气都是晴天,只有下雨天这个线程才会去工作,那么我就需要这个线程睡眠,不要浪费CPU 资源,等下雨时我再叫醒它起来工作就行了,线程条件变量就是扮演这样一个角色。
        条件的检测是在互斥锁的保护下进行的。线程在改变条件状态之前必须首先锁住互斥量。如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两进程共享可读写的内存,条件变量 可以被用来实现这两进程间的线程同步。
        在 linux 的 pthread 中使用条件变量的类型为:pthread_cond_t 表示一个条件变量
typedef union
{
        struct __pthread_mutex_s __data ;
        char __size [ __SIZEOF_PTHREAD_MUTEX_T ];
        long int __align ;
} pthread_mutex_t ;
对线程条件变量的操作可以有
1.初始化条件变量
2.销毁条件变量
3.等待条件变量(线程睡眠)
4.唤醒等待条件变量的线程

初始化条件变量

动态初始化(pthread_cond_init)

头文件:
#include <pthread.h>
函数原型:
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
作用:
        初始化线程条件变量 cond
参数含义:
        cond:线程条件变量
        attr:线程条件变量的属性,为空表示默认属性
返回值:
        成功返回 0,
        失败返回错误号

静态初始化

在 linux 中使用静态存储区中的 PTHREAD_COND_INITIALIZER 就可以对条件变量完成静
态初始化
/* Conditional variable handling. */
#define PTHREAD_COND_INITIALIZER { { { 0 }, { 0 }, { 0 , 0 }, { 0 , 0 }, 0 , 0 , { 0 , 0 } } }
如下:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

销毁条件变量(pthread_cond_destroy)

头文件:
#include <pthread.h>
函数原型:
int pthread_cond_destroy(pthread_cond_t *cond);
作用:
        销毁线程条件变量 cond
参数含义:
         cond: 线程条件变量
返回值:
        成功返回 0,
        失败返回错误号

等待一个条件变量(线程睡眠)

阻塞等待(pthread_cond_wait)

头文件:
#include <pthread.h>
函数原型:
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
作用:
        阻塞等待条件变量 cond 的值,线程进入睡眠状态并解锁,直到被条件变量唤醒
参数含义:
        cond:线程条件变量
        mutex:互斥锁
返回值:
        成功返回 0,
        失败返回错误号
备注:
        1.因为条件变量本身是一个“共享资源”,为了避免竞争,需要一个线程互斥锁来保护
        2.在 pthread_cond_wait/pthread_cond_timewait 需要把锁住的互斥锁传入函数,在函数内部实现的时候,线程让出 CPU(休眠)前,释放传入的互斥锁,然后再休眠
        3.休眠到直到条件发生(被唤醒),被唤醒的时候,再次重新锁住传入的锁(不会带锁休眠),也就是说线程在睡眠的时候会解锁,在被唤醒时会去获取锁

限时等待(pthread_cond_timedwait)

头文件:
#include <pthread.h>

函数原型:

int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);
作用:
        限时等待条件变量 cond 的值,线程进入睡眠状态并解锁,直到被条件变量唤醒或到达绝对时间 abstime
参数含义:
        cond:线程条件变量
        mutex:互斥锁
        abstime: 是一个绝对时间(当前时间+等待时间),表示超过这个时间将直接返回
返回值:
        成功返回 0,
        失败返回错误号

唤醒等待条件变量的线程

唤醒所有等待该条件变量的线程(pthread_cond_broadcast)

头文件:
#include <pthread.h>
函数原型:
int pthread_cond_broadcast(pthread_cond_t *cond);
作用:
        唤醒所有等待条件变量 cond 的线程
参数含义:
        cond:线程条件变量
返回值:
        成功返回 0,
        失败返回错误号

唤醒一个等待该条件变量的线程(pthread_cond_signal)

头文件:
#include <pthread.h>
函数原型:
int pthread_cond_signal(pthread_cond_t *cond);
作用:
        激活一个等待该条件 cond 的线程,存在多个等待线程时按入队顺序激活其中一个;
参数含义:
        cond:线程条件变量
返回值:
        成功返回 0,
        失败返回错误号
备注:
        在生产者消费者模型中,如果生产者一次性可以产出多个任务,那么用 pthread_cond_broadcast 好一点,如果溢出只产生一个任务,那么使用pthread_cond_signal 好一点

使用示例

#include <stdio.h>
#include <pthread.h>
static pthread_t thread1;
static pthread_t thread2;//静态初始化
static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
void *function1()
{while(1){pthread_mutex_lock(&lock);printf("===== 线程 1 进入睡眠 ====\n");pthread_cond_wait(&cond,&lock);printf("==== 线程 1 唤醒 ====\n");pthread_mutex_unlock(&lock);}
}void *function2()
{while(1){pthread_mutex_lock(&lock);printf("===== 线程 2 进入睡眠 ====\n");pthread_cond_wait(&cond,&lock);printf("==== 线程 2 唤醒 ====\n");pthread_mutex_unlock(&lock);}
}int main()
{int i=0;if(-1==pthread_create(&thread1,NULL,function1,NULL)){printf("thread_create1 fail!\n");pthread_detach(thread1);}if(-1==pthread_create(&thread2,NULL,function2,NULL)){printf("thread_create fail!\n");pthread_detach(thread1);}while(1){sleep(2);i++;printf("\n 第%d 次唤醒\n",i);pthread_mutex_lock(&lock);if(-1==pthread_cond_signal(&cond)){printf("pthread_cond_broadcast error!\n");}pthread_mutex_unlock(&lock);}return 0;
}

相关文章:

linux-线程条件变量(cond)

概述 与互斥锁不同&#xff0c;条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程&#xff0c;直到某特殊情况发生为止。通常条件变量和互斥锁同时使用 。 条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制&a…...

面试算法6:排序数组中的两个数字之和

题目 输入一个递增排序的数组和一个值k&#xff0c;请问如何在数组中找出两个和为k的数字并返回它们的下标&#xff1f;假设数组中存在且只存在一对符合条件的数字&#xff0c;同时一个数字不能使用两次。例如&#xff0c;输入数组[1&#xff0c;2&#xff0c;4&#xff0c;6&…...

【智能家居-大模型】构建未来,聆思大模型智能家居交互解决方案正式发布

LISTENAI 近日&#xff0c;国内11家大模型陆续通过《生成式人工智能服务管理暂行办法》备案&#xff0c;多家大模型产品已正式开放&#xff0c;激发了新一轮大模型热潮。大模型在自然语言理解方面的巨大突破&#xff0c;实现了认知智能的技术跃迁&#xff0c;带来了时代的智慧…...

通讯网关软件002——利用CommGate X2HTTP-U实现HTTP访问OPC UA Server

本文介绍利用CommGate X2HTTP-U实现HTTP访问OPC UA Server。CommGate X2HTTP是宁波科安网信开发的网关软件&#xff0c;软件可以登录到网信智汇(wangxinzhihui.com)下载。 【案例】如下图所示&#xff0c;实现上位机通过HTTP来获取OPC UA Server的数据。 【解决方案】设置网关机…...

模拟经营类游戏是怎么开发的?

模拟经营类游戏开发是一个充满挑战但也充满乐趣的领域。下面是一些步骤和关键考虑因素&#xff0c;可以帮助您开始开发自己的模拟经营游戏&#xff1a; 明确游戏概念&#xff1a; 确定游戏开发的主题和类型&#xff0c;例如城市建设、农场经营、餐厅经营等。 制定一个引人入胜…...

基于JAVA+SSM+微信小程序+MySql的图书捐赠管理系统设计与实现

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 在当今社会&#xff0…...

软件设计模式系列之六——单例模式

1 模式的定义 单例模式&#xff08;Singleton Pattern&#xff09;是一种常见的创建型设计模式&#xff0c;其主要目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。这意味着无论何时何地&#xff0c;只要需要该类的实例&#xff0c;都会返回同一个…...

verdi dump状态机的波形时直接显示状态名

前段时间看到别人用verdi看状态机的波形时&#xff0c;可以显示定义的状态参数&#xff0c;觉得很有意思&#xff0c;特地学习了一下 通常拉出状态机信号的波形是下面这样的 这种信号&#xff0c;我们要想知道每个数值代表的状态&#xff0c;还需要跟定义的parameter比对 像这…...

代码随想录算法训练营19期第53天

1143.最长公共子序列 视频讲解&#xff1a;动态规划子序列问题经典题目 | LeetCode&#xff1a;1143.最长公共子序列_哔哩哔哩_bilibili 代码随想录 初步思路&#xff1a;动态规划。 总结&#xff1a; dp[i][j] &#xff1a;长度为[0, i - 1]的字符串A与长度为[0, j - 1]…...

二刷力扣--栈和队列

栈和队列 栈和队列基础&#xff08;Python&#xff09; 栈一种先进后出&#xff0c;队列先进后出。 Python中可以用list实现栈&#xff0c;用append()模拟入栈&#xff0c;用pop()模拟出栈。 也可以用list实现队列&#xff0c;但是效率较低&#xff0c;一般用collections.deq…...

第六章 图 十、关键路径

开始顶点&#xff08;源点)&#xff1a; 在AOE网中仅有一个入度为0的顶点&#xff0c;称为开始顶点&#xff08;源点)&#xff0c;它表示整个工程的开始; 结束顶点&#xff08;汇点)&#xff1a; 也仅有一个出度为0的顶点&#xff0c;称为结束顶点&#xff08;汇点)&#xf…...

Virtualbox固定存储硬盘转换为动态存储硬盘

现象 一开始分配固定存储过大&#xff0c;占了太多空间&#xff0c;现在想换成动态存储释放空闲空间。 解决 关闭虚拟机进入虚拟介质管理从使用的硬盘复制出一个动态存储硬盘在设置中把硬盘替换为副本硬盘 详细步骤参考&#xff1a; https://blog.csdn.net/qq_24033983/arti…...

【栈与队列面试题】有效的括号(动图演示)

leetcode20.括号匹配问题 前言&#xff1a; &#x1f4a5;&#x1f388;个人主页:​​​​​​Dream_Chaser&#xff5e; &#x1f388;&#x1f4a5; ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣上栈与队列的面试OJ题目 目录 leetcode20.括号匹配问题 1.问题描…...

基于matlab实现的弹簧振动系统模型程序(动态模型)

完整代码&#xff1a; clear all; %System data m1.0; zeta0.01; omega01.0; Dt1.0; f01.0; x00.0; dotx00.0; xmaxsqrt(x0^2(dotx0/omega0)^2)min([0.5*abs(f0)*Dt/(m*omega0) f0/omega0^2]); omegadomega0*sqrt(1-zeta^2); dt00.1*pi/omega0; nstep500; a0.70; b0.…...

哨兵1号(Sentinel-1)SAR卫星介绍

1. 哥白尼计划 说起欧空局的哨兵1号&#xff0c;就不得不先说一下欧空局的“哥白尼计划”。 欧空局的哥白尼计划&#xff08;Copernicus Programme&#xff09;是欧空局与欧盟合作的一项极其重要的地球观测计划。该计划旨在提供免费开放的、可持续的地球观测数据&#xff0c…...

[maven] scopes 管理 profile 测试覆盖率

[maven] scopes & 管理 & profile & 测试覆盖率 这里将一些其他的特性和测试覆盖率&#xff08;主要是 jacoco&#xff09; scopes maven 的 scope 主要就是用来限制和管理依赖的传递性&#xff0c;简单的说就是&#xff0c;每一个 scope 都有其对应的特性&…...

css网页打印字体设置

media print {font-family&#xff1a;"SimHei";color: #000;border-color: #000; }常用字符编码表 中文名英文名Unicode 编码黑体SimHeiSimHei微软雅黑Microsoft YaHei5FAE\8F6F\96C5\9ED1宋体SimSun\5B8B\4F53仿宋FangSong\4EFF\5B8B html5常用转义字符℃ 字符十…...

JAVA高级技术入门(单元测试,反射,注解,动态代理)

JAVA高级技术入门&#xff08;单元测试&#xff0c;反射&#xff0c;注解&#xff0c;动态代理&#xff09; 一、Junit单元测试二、反射1.认识反射&#xff0c;获取类概念&#xff1a;快速入门&#xff1a;获取Class对象的三种方式 2.1获取类的构造器2.2获取类的构造器的作用&a…...

uni-app 实现自定义按 A~Z 排序的通讯录(字母索引导航)

创建 convertPinyin.js 文件 convertPinyin.js 将下面的内容复制粘贴到其中 const pinyin (function() {let Pinyin function(ops) {this.initialize(ops);},options {checkPolyphone: false,charcase: "default"};Pinyin.fn Pinyin.prototype {init: functi…...

C++ PrimerPlus 复习 第一章 命令编译链接文件 make文件

第一章 命令编译链接文件 C 有什么呢&#xff1f;C 源代码文件后缀运行C过程可执行代码&#xff1a;编译语法&#xff1a;makeMakefile 基础语法编写完make只要和将要编译的文件放一起就行 然后在该目录使用make命令&#xff0c;就将自动运行&#xff1b;基础的Makefile版本 现…...

ViGEmBus如何解决Windows游戏控制器兼容性难题?

ViGEmBus如何解决Windows游戏控制器兼容性难题&#xff1f; 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus ViGEmBus是一款专业的Windows内核模式驱动程序&a…...

OpenClaw+GLM-4.7-Flash学习助手:自动整理课程笔记与生成复习题

OpenClawGLM-4.7-Flash学习助手&#xff1a;自动整理课程笔记与生成复习题 1. 为什么需要自动化学习助手&#xff1f; 去年备考研究生时&#xff0c;我每天要处理3-4小时的课程视频。最痛苦的不是听课本身&#xff0c;而是课后整理&#xff1a;手动截取关键片段、转录字幕、标…...

智能记账本:OpenClaw+Qwen3.5-9B自动归类信用卡消费邮件

智能记账本&#xff1a;OpenClawQwen3.5-9B自动归类信用卡消费邮件 1. 为什么需要自动化记账工具 每次收到银行消费短信时&#xff0c;我都会陷入两难&#xff1a;手动记账太繁琐&#xff0c;不记账又会导致月度消费分析失真。传统记账软件需要手动输入金额和分类&#xff0c…...

OpenClaw环境迁移:GLM-4.7-Flash配置的备份与恢复方案

OpenClaw环境迁移&#xff1a;GLM-4.7-Flash配置的备份与恢复方案 1. 为什么需要环境迁移&#xff1f; 上周我的主力开发机突然硬盘故障&#xff0c;导致所有OpenClaw配置丢失。最痛心的是花了两周调试的GLM-4.7-Flash对接设置全部归零——包括精心调整的温度参数、自定义提示…...

解锁新可能:ArkData 在智能穿戴设备中的应用

解锁新可能&#xff1a;ArkData 在智能穿戴设备中的应用随着人们对健康生活的重视&#xff0c;智能穿戴设备愈发普及。这些设备能够实时收集心率、步数、睡眠等健康数据&#xff0c;为人们的健康管理提供重要参考。在这一背景下&#xff0c;如何高效管理和利用这些健康数据成为…...

SpeedyStepper Forked:嵌入式步进电机硬实时控制库解析

1. SpeedyStepper Forked&#xff1a;面向嵌入式实时控制的高性能步进电机驱动库深度解析1.1 库定位与工程价值SpeedyStepper Forked 是一个专为嵌入式平台&#xff08;尤其是基于Arduino生态的MCU&#xff09;设计的轻量级、高精度步进电机运动控制库。其核心目标并非提供图形…...

从机器人ROS2到微服务gRPC:手把手教你用IDL定义跨语言通信的‘世界语’

从机器人ROS2到微服务gRPC&#xff1a;手把手教你用IDL定义跨语言通信的‘世界语’ 清晨的阳光透过实验室的玻璃窗洒进来&#xff0c;机械臂正在执行预设的轨迹动作&#xff0c;而云端的数据分析服务实时监控着它的能耗曲线。这个看似简单的场景背后&#xff0c;隐藏着一个复杂…...

Windows 内网 Web 服务穿透方案推荐

Windows 内网 Web 服务穿透方案推荐 面向场景&#xff1a;内网机器为 Windows&#xff0c;需从公网或外网访问内网 HTTP/HTTPS Web 服务&#xff1b;优先选择相对不易被误报、来源清晰、可审计的方案。 关于「报毒」的说明 穿透类软件常被启发式引擎标为「风险/可疑」&#xf…...

[FFXIVChnTextPatch]:国际服中文补丁解决方案——从入门到精通

[FFXIVChnTextPatch]&#xff1a;国际服中文补丁解决方案——从入门到精通 【免费下载链接】FFXIVChnTextPatch 项目地址: https://gitcode.com/gh_mirrors/ff/FFXIVChnTextPatch 一、问题引入&#xff1a;当语言成为游戏体验的隐形壁垒 你是否曾在探索艾欧泽亚大陆时…...

OpenClaw任务编排:GLM-4.7-Flash复杂流程设计

OpenClaw任务编排&#xff1a;GLM-4.7-Flash复杂流程设计 1. 为什么需要任务编排 去年我接手了一个市场分析项目&#xff0c;需要每周手动收集竞品动态并生成报告。重复性的复制粘贴和格式调整消耗了大量时间&#xff0c;直到发现OpenClaw可以通过编排GLM-4.7-Flash模型实现全…...