在C语言中使用条件变量实现线程同步
互斥量、原子操作都是实现线程同步的方法,今日介绍使用条件变量来实现线程同步。在多线程应用中,当某个线程的执行依赖于另一个线程对数据的处理时,这个线程可能没有被阻塞,只是不断地检查某个条件是否成立了(这个条件就是另一个线程对数据处理的结果的指示器),这是一种“忙等待”的方式实现线程间的同步。在实践中应该避免使用,因为忙等待需要让线程反复检查某个条件是否为真,浪费大量宝贵的 CPU 资源在无用的活动上。使用条件变量既可以尽量减少处理器资源的浪费,又能够解决线程间数据依赖的问题。
C 标准库还提供了与条件变量相关的常用函数:
- cnd_signal:发送条件变量,唤醒阻塞在cnd_wait调用处的线程
- cnd_wait:阻塞线程,将线程加入等待队列,将会被cnd_signal唤醒
- cnd_broadcast:唤醒所有在等待某个条件变量的线程
- cnd_timedwait:带超时限制的cnd_wait
实例如下:
#include <threads.h>
#include <stdio.h>mtx_t mutex;// 互斥量
cnd_t cond; // 条件变量
int done = 0;
int run(void* arg){mtx_lock(&mutex);//加锁done = 1;cnd_signal(&cond);//发送条件信号mtx_unlock(&mutex);//解锁return thrd_success;
}int main(void){
#ifndef __STDC_NO_THREADS__mtx_init(&mutex,mtx_plain);//初始化互斥量cnd_init(&cond);//初始化条件变量thrd_t thread;thrd_create(&thread,run,NULL);//创建线程mtx_lock(&mutex);//加锁while(done == 0){cnd_wait(&cond,&mutex);//让当前线程进入等待队列,后续被唤醒后,互斥量会再次上锁} mtx_unlock(&mutex);//解锁printf("The value of done is %d.\n",done);mtx_destroy(&mutex); cnd_destroy(&cond); // 销毁条件变量
#endifreturn 0;
}
在上述程序中,在 main 线程中,调用了与条件变量相关的函数 cnd_wait。该函数在被调用时,需要当前线程获得一个互斥锁,并将其作为实参传递给它,该函数调用后锁会被释放。同时,所有执行到此处的线程都将被阻塞。
子线程会执行run方法,run方法里会对done加1,然后调用函数 cnd_signal发送条件信号,唤醒所有之前被阻塞在函数 cnd_wait 处的线程,来让它们中的一个可以继续运行。在我们的例子中,只有 main 函数对应的一个线程,所以此时,互斥量将被重新上锁,main 线程将继续执行接下来的指令。
这样一来,某个线程可以在完成了某件事情后,通知并唤醒等待线程,让其继续工作,完成接下来的任务。而在此过程中,不需要线程频繁查询标志量。CPU 资源也得到了更好的利用。在并发编程中,通过条件变量,可以进一步实现监视器、管程等工具和同步原语。它也能够很好地解决生产者 - 消费者问题。
相关文章:
在C语言中使用条件变量实现线程同步
互斥量、原子操作都是实现线程同步的方法,今日介绍使用条件变量来实现线程同步。在多线程应用中,当某个线程的执行依赖于另一个线程对数据的处理时,这个线程可能没有被阻塞,只是不断地检查某个条件是否成立了(这个条件…...
图书管理系统 Axios 源码__新增图书
目录 功能介绍 核心代码解析 源码:新增图书功能 总结 本项目基于 HTML、Bootstrap、JavaScript 和 Axios 开发,实现了图书的增删改查功能。以下是新增图书的功能实现,适合前端开发学习和项目实践。 功能介绍 用户可以通过 模态框…...
Maven全解析:从基础到精通的实战指南
概念: Maven 是跨平台的项目管理工具。主要服务基于 Java 平台的构建,依赖管理和项目信息管理项目构建:高度自动化,跨平台,可重用的组件,标准化的流程 依赖管理: 对第三方依赖包的管理…...
数据密码解锁之DeepSeek 和其他 AI 大模型对比的神秘面纱
本篇将揭露DeepSeek 和其他 AI 大模型差异所在。 目录 编辑 一本篇背景: 二性能对比: 2.1训练效率: 2.2推理速度: 三语言理解与生成能力对比: 3.1语言理解: 3.2语言生成: 四本篇小结…...
python算法和数据结构刷题[5]:动态规划
动态规划(Dynamic Programming, DP)是一种算法思想,用于解决具有最优子结构的问题。它通过将大问题分解为小问题,并找到这些小问题的最优解,从而得到整个问题的最优解。动态规划与分治法相似,但区别在于动态…...
Ollama+OpenWebUI部署本地大模型
OllamaOpenWebUI部署本地大模型 前言 Ollama是一个强大且易于使用的本地大模型推理框架,它专注于简化和优化大型语言模型(LLMs)在本地环境中的部署、管理和推理工作流。可以将Ollama理解为一个大模型推理框架的后端服务。 Ollama Ollama安…...
Python从0到100(八十六):神经网络-ShuffleNet通道混合轻量级网络的深入介绍
前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…...
【网络】传输层协议TCP(重点)
文章目录 1. TCP协议段格式2. 详解TCP2.1 4位首部长度2.2 32位序号与32位确认序号(确认应答机制)2.3 超时重传机制2.4 连接管理机制(3次握手、4次挥手 3个标志位)2.5 16位窗口大小(流量控制)2.6 滑动窗口2.7 3个标志位 16位紧急…...
海思ISP开发说明
1、概述 ISP(Image Signal Processor)图像信号处理器是专门用于处理图像信号的硬件或处理单元,广泛应用于图像传感器(如 CMOS 或 CCD 传感器)与显示设备之间的信号转换过程中。ISP通过一系列数字图像处理算法完成对数字…...
实验十 Servlet(一)
实验十 Servlet(一) 【实验目的】 1.了解Servlet运行原理 2.掌握Servlet实现方式 【实验内容】 1、参考课堂例子,客户端通过login.jsp发出登录请求,请求提交到loginServlet处理。如果用户名和密码相同则视为登录成功,…...
doris:聚合模型的导入更新
这篇文档主要介绍 Doris 聚合模型上基于导入的更新。 整行更新 使用 Doris 支持的 Stream Load,Broker Load,Routine Load,Insert Into 等导入方式,往聚合模型(Agg 模型)中进行数据导入时,都…...
Java NIO_非阻塞I/O的实现与优化
1. 引言 1.1 背景介绍 随着互联网应用的快速发展,传统的阻塞I/O模型已经无法满足高并发、高性能的需求。Java NIO(Non-blocking I/O)提供了高效的非阻塞I/O操作,使得开发者能够构建高性能的网络应用和文件处理系统。 1.2 Java NIO的重要性 Java NIO通过非阻塞I/O和多路…...
代码随想录算法训练营Day51 | 101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
文章目录 101.孤岛的总面积思路与重点 102.沉没孤岛思路与重点 103.水流问题思路与重点 104.建造最大岛屿思路与重点 101.孤岛的总面积 题目链接:101.孤岛的总面积讲解链接:代码随想录状态:直接看题解了。 思路与重点 nextx或者nexty越界了…...
Games202Lecture 6 Real-time Environment Mapping
RTRT RTRT(real time ray tracing): path tracingdenoising PRT PRT (Precomputed radiance transfer):离线预计算,运行时快速内积。 预计算(Offline Precomputation): 传输函数(Transfer Function&…...
在 Zemax 中使用布尔对象创建光学光圈
在 Zemax 中,布尔对象用于通过组合或减去较简单的几何形状来创建复杂形状。布尔运算涉及使用集合运算(如并集、交集和减集)来组合或修改对象的几何形状。这允许用户在其设计中为光学元件或机械部件创建更复杂和定制的形状。 本视频中…...
MySQL知识点总结(十八)
说明你对InnoDB集群的整体认知。 MySQL组复制技术是InnoDB集群实现的基础,组复制安装在集群中的每个服务器实例上。组复制能够创建弹性复制拓扑,在集群中的服务器脱机时可以自动重新配置自己。必须至少有三台服务器才能组成一个可以提供高可用性的组。组…...
[论文总结] 深度学习在农业领域应用论文笔记14
当下,深度学习在农业领域的研究热度持续攀升,相关论文发表量呈现出迅猛增长的态势。但繁荣背后,质量却不尽人意。相当一部分论文内容空洞无物,缺乏能够落地转化的实际价值,“凑数” 的痕迹十分明显。在农业信息化领域的…...
MySQL和Redis的区别
MySQL和Redis都是流行的数据存储解决方案,但它们在设计、用途和特性上有显著区别。理解这些区别有助于选择合适的数据库来满足不同的应用需求。本文将详细介绍MySQL和Redis的区别,包括它们的架构、使用场景、性能和其他关键特性。 一、基本概述 MySQL&…...
Rust 中的注释使用指南
Rust 中的注释使用指南 注释是代码中不可或缺的一部分,它帮助开发者理解代码的逻辑和意图。Rust 提供了多种注释方式,包括行注释、块注释和文档注释。本文将详细介绍这些注释的使用方法,并通过一个示例展示如何在实际代码中应用注释。 1. 行…...
2025年2月2日(tcp3次握手4次挥手)
TCP(三次握手和四次挥手)是建立和关闭网络连接的标准过程,确保数据在传输过程中可靠无误。下面是详细解释: 1. 三次握手(TCP连接建立过程) 三次握手是为了在客户端和服务器之间建立一个可靠的连接&#x…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...
VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...
