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

多线程编程技术解析及示例:pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock

多线程编程技术解析及示例:pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock

摘要

本文深入解析了多线程编程中 pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock 三个函数的功能、使用场景及注意事项,并通过结合三者的生产者 - 消费者模型 C 语言示例程序,生动展示了它们在实际多线程任务调度中的应用。同时对锁顺序、条件变量使用以及错误处理等关键要点进行了总结,为开发者在多线程环境下的高效编程与问题解决提供参考。

pthread_mutex_lock 解析

  • 功能 :实现阻塞式加锁,当锁被其他线程占用时,调用该函数的线程会挂起等待,直至获取到锁。

  • 使用场景

    • 严格保护临界区,防止多个线程同时访问导致数据不一致,如对共享变量、关键数据结构的操作区域进行保护。
    • 确保线程按既定顺序访问共享资源,维持程序的正确执行流程。
  • 注意事项

    • 必须与 pthread_mutex_unlock 成对使用,否则将导致死锁,线程无法继续推进,程序陷入僵局。
    • 非递归属性下不可递归调用,若需递归加锁,应使用 PTHREAD_MUTEX_RECURSIVE 属性进行设置。

pthread_mutex_trylock 解析

  • 功能 :以非阻塞方式尝试加锁,无论是否成功获取锁,都会立即返回相应结果,获取成功返回 0,失败则返回 EBUSY 错误码。

  • 使用场景

    • 在尝试获取多个锁时,若获取其中一个锁失败,可及时释放已持有的其他锁,避免死锁发生,提高程序的健壮性。
    • 适用于轻量级任务调度,如需确保同一时刻仅有一个线程执行的单例任务场景。
  • 注意事项

    • 获取锁失败时,必须妥善处理 EBUSY 错误,不能直接进入临界区操作数据,防止数据混乱。
    • 不可与 pthread_mutex_lock 混用,以免造成锁机制混乱,出现不可预期的错误。

pthread_cond_timedwait 解析

  • 功能 :提供带超时机制的条件变量等待操作,需与互斥锁配合使用,线程在等待过程中会释放锁,在超时或被唤醒时重新尝试获取锁。

  • 使用场景

    • 在生产者 - 消费者模型中,消费者可利用该函数等待任务,若超时未获取到任务,可执行相应超时处理逻辑。
    • 当线程需在特定时间内响应条件变化时,如实时性要求较高的任务调度场景。
  • 注意事项

    • 超时时间应设置为绝对时间,一般通过 CLOCK_REALTIME 获取当前时间并加上期望的等待时长来确定。
    • 因可能存在虚假唤醒现象,必须在循环中检查条件是否真正满足,若不满足则继续等待。
    • 调用前确保已锁定互斥锁,返回后线程自动重新加锁,这是保证数据安全和等待逻辑正确的关键。

C 语言示例程序

以下是一个结合 pthread_mutex_lock、pthread_mutex_trylock 和 pthread_cond_timedwait 的生产者 - 消费者模型示例程序,展示了它们在实际场景下的协同工作方式:

#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int task_available = 0;void* producer(void* arg) {while (1) {pthread_mutex_lock(&mutex);task_available = 1;printf("Produced task\n");pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);sleep(1);}return NULL;
}void* consumer(void* arg) {struct timespec ts;while (1) {pthread_mutex_lock(&mutex);clock_gettime(CLOCK_REALTIME, &ts);ts.tv_sec += 2; // 设置 2 秒超时while (!task_available) {if (pthread_cond_timedwait(&cond, &mutex, &ts) == ETIMEDOUT) {printf("Timeout, no task\n");break;}}if (task_available) {printf("Consumed task\n");task_available = 0;}pthread_mutex_unlock(&mutex);// 非阻塞尝试其他操作if (pthread_mutex_trylock(&mutex) == 0) {printf("Doing non-critical work\n");pthread_mutex_unlock(&mutex);}}return NULL;
}int main() {pthread_t prod, cons;pthread_create(&prod, NULL, producer, NULL);pthread_create(&cons, NULL, consumer, NULL);pthread_join(prod, NULL);pthread_join(cons, NULL);return 0;
}

关键总结

锁顺序

在涉及多把锁的场景中,为防止死锁,建议按照固定的顺序加锁。例如,若存在锁 A 和锁 B,所有线程在获取锁时应统一先获取锁 A,再获取锁 B,从而避免因加锁顺序不一致导致的相互等待僵局。

条件变量

使用条件变量时,由于可能存在虚假唤醒(即线程被唤醒但条件并未真正满足),必须在循环中反复检查条件是否满足,若不满足则继续等待,以确保程序逻辑的正确性。

错误处理

在调用 pthread_cond_timedwait 时,要检查其返回值是否为 ETIMEDOUT,以判断是正常被唤醒还是因超时退出等待;对于 pthread_mutex_trylock,需处理返回的 EBUSY 错误码,避免因获取锁失败而直接进入临界区引发的问题。

相关文章:

多线程编程技术解析及示例:pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock

多线程编程技术解析及示例&#xff1a;pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock 摘要 本文深入解析了多线程编程中 pthread_cond_timedwait、pthread_mutex_lock 和 pthread_mutex_trylock 三个函数的功能、使用场景及注意事项&#xff0c;并通…...

vue实现点击单选或者多选模式

toggleSelect(item) { if (!this.single) { // 多选模式 const itemIndex this.selectedItems.findIndex( (selectedItem) > selectedItem.userId item.userId ); // 假设每个对象都有一个唯一的id属性 if (itemIndex ! -1) { this.selectedItems.splice(itemIndex, 1); }…...

Windows系统工具:WinToolsPlus 之 SQL Server 日志清理

使用软件时提示数据库事务日志已满&#xff0c; 使用WinToolsPlus 数据库页签 先设置 数据源 &#xff0c; 选择 需要清理日志的数据库&#xff0c; 点击 数据库日志清理 即可。 下载地址&#xff1a; http://v.s3.sh.cn/archives/2279.html...

在Windows11上安装 Ubuntu WSL

不想安装虚拟机,想在Windows11上运行Linux。网上虽有教程,但是图片明显都是老图,与Windows11还是有些差异。网上缺乏一个齐全的真正的Windows11运行Linux的教程。 一、在Windows上的设置 1. 在window11的搜索框内(所有你找不到的应用都可以用这个搜索功能)&#xff0c;搜索&q…...

嵌入式Linux之RK3568

系统烧写镜像。 1、直接使用正点原子官方的updata.img(MIDP) 进入瑞芯微发开工具RKDevTool&#xff0c;选择升级固件&#xff0c;上传到固件&#xff0c;记住这里要进入maskrom模式或者是loader模式&#xff0c;进入该模式之后点击升级即可。 2、烧入自己制作的镜像(单独、一…...

Elasticsearch的插件(Plugin)系统介绍

Elasticsearch的插件(Plugin)系统是一种扩展机制,允许用户通过添加自定义功能来增强默认功能,而无需修改核心代码。插件可以提供从分析器、存储后端到安全认证、机器学习等各种功能,使Elasticsearch能够灵活适应不同的应用场景和业务需求。 一、插件的核心特点 模块化扩展…...

提取 PDF 文件中的文字以及图片中的文字

Adobe 提供了多种方案可以快速提取 PDF 文件中的文字以及图片中的文字&#xff0c;主要依赖其 Acrobat 系列产品和 OCR&#xff08;光学字符识别&#xff09;技术。以下是具体解决方案的概述&#xff0c;涵盖了文字和图片文字的提取方法&#xff1a; 1. 提取 PDF 中的文字 如果…...

JavaScript性能优化实战技术

目录 性能优化核心原则 代码层面优化 加载优化策略 内存管理实践 及时解除事件监听 避免内存泄漏模式 渲染性能调优 使用requestAnimationFrame优化动画 批量DOM操作减少回流 性能监控工具 现代API应用 缓存策略实施 性能优化核心原则 减少资源加载时间 避免阻塞主…...

LeetCode 热题 100 739. 每日温度

LeetCode 热题 100 | 739. 每日温度 大家好&#xff0c;今天我们来解决一道经典的算法题——每日温度。这道题在 LeetCode 上被标记为中等难度&#xff0c;要求我们找到一个数组&#xff0c;其中每个元素表示从当前天开始&#xff0c;下一个更高温度出现的天数。如果之后没有更…...

网页前端开发(基础进阶3--Vue)

Vue3 Vue是一款用于构建用户界面的渐进式的JavaScript框架。 Vue由2部分组成&#xff1a;Vue核心包&#xff0c;Vue插件包 Vue核心包包含&#xff1a;声明式渲染&#xff0c;组件系统。 Vue插件包&#xff1a;VueRouter&#xff08;客户端路由&#xff09;&#xff0c;Vuex…...

tryhackme——Abusing Windows Internals(进程注入)

文章目录 一、Abusing Processes二、进程镂空三、线程劫持四、DLL注入五、Memory Execution Alternatives 一、Abusing Processes 操作系统上运行的应用程序可以包含一个或多个进程&#xff0c;进程表示正在执行的程序。进程包含许多其他子组件&#xff0c;并且直接与内存或虚…...

【游戏科学】游戏开发中数学算法的核心与应用

一、游戏科学&#xff08;Game Science&#xff09; 涉及大量数学算法和模型&#xff0c;用于实现物理模拟、图形渲染、人工智能、路径规划、碰撞检测等核心功能。 1.1、图形渲染与几何计算 1. 三维变换&#xff08;3D Transformations&#xff09; 矩阵变换&#xff1a; 模…...

【Day44】

DAY 44 预训练模型 知识点回顾&#xff1a; 预训练的概念常见的分类预训练模型图像预训练模型的发展史预训练的策略预训练代码实战&#xff1a;resnet18 作业&#xff1a; 尝试在cifar10对比如下其他的预训练模型&#xff0c;观察差异&#xff0c;尽可能和他人选择的不同尝试通…...

基于 Alpine 定制单功能用途(kiosk)电脑

前言 故事回到 7 年前, 在网上冲浪的时候发现了一篇介绍使用 Ubuntu 打造 kiosk 单功能用途电脑的文章, 挺好玩的, 就翻译了一下并比葫芦画瓢先后用了 CentOS 7, ArchLinux 进行了实现. 历史文章: 翻译 - 使用Ubutnu14.04和Chrome打造单功能用途电脑(大屏展示电脑) 使用CentOS…...

知识图谱系统功能实现,技术解决方案,附源码

基于Java、Neo4j和ElasticSearch构建的医疗知识图谱知识库&#xff0c;是一个融合图数据库技术与搜索引擎的智能化医疗知识管理系统。该系统以Neo4j图数据库为核心&#xff0c;利用其高效的图结构存储能力&#xff0c;将疾病、症状、药品、检查项目、科室等医疗实体抽象为节点&…...

第12节 Node.js 函数

在JavaScript中&#xff0c;一个函数可以作为另一个函数接收一个参数。我们可以先定义一个函数&#xff0c;然后传递&#xff0c;也可以在传递参数的地方直接定义函数。 Node.js中函数的使用与Javascript类似&#xff0c;举例来说&#xff0c;你可以这样做&#xff1a; funct…...

洛谷P12610 ——[CCC 2025 Junior] Donut Shop

题目背景 Score: 15. 题目描述 The owner of a donut shop spends the day baking and selling donuts. Given the events that happen over the course of the day, your job is to determine the number of donuts remaining when the shop closes. 输入格式 The first …...

1. 数据库基础

1.1 什么是数据库 ⭐ mysql 本质是一种网络服务, 是基于 C(mysql) S(mysqld)的 网络服务. 存储数据用文件就可以了&#xff0c;为什么还要弄个数据库&#xff1f;文件保存数据存在以下缺点&#xff1a; 文件的安全性问题。文件不利于数据查询和管理。文件不利于存储海量数据。…...

英伟达288GB HBM4+50P算力

英伟达CEO黄仁勋在COMPUTEX 2025上突然官宣&#xff1a;以暗物质研究先驱Vera Rubin命名的新一代AI芯片即将量产&#xff01;这颗被称作“算力巨兽”的Rubin GPU&#xff0c;不仅搭载288GB HBM4显存和50 Petaflops推理算力&#xff0c;更携三大颠覆性技术直击AI行业痛点。更可怕…...

【Pandas】pandas DataFrame reset_index

Pandas2.2 DataFrame Reindexing selection label manipulation 方法描述DataFrame.add_prefix(prefix[, axis])用于在 DataFrame 的行标签或列标签前添加指定前缀的方法DataFrame.add_suffix(suffix[, axis])用于在 DataFrame 的行标签或列标签后添加指定后缀的方法DataFram…...

综合案例:斗地主

综合案例&#xff1a;斗地主 1.程序概述 这是一个模拟斗地主游戏发牌过程的C语言程序&#xff0c;实现了扑克牌的初始化、洗牌和发牌功能。 2.功能需求 2.1 扑克牌定义 使用结构体 Card 表示一张牌&#xff0c;包含&#xff1a; 花色属性suit&#xff08;0-3表示普通花色♥…...

前端组件推荐 Swiper 轮播与 Lightbox 灯箱组件深度解析

在互联网产品不断迭代升级的今天&#xff0c;用户对于页面交互和视觉效果的要求越来越高。想要快速打造出吸睛又实用的项目&#xff0c;合适的组件必不可少。今天就为大家推荐两款超好用的组件 ——Swiper 轮播组件和 Lightbox 灯箱组件&#xff0c;轻松解决你的展示难题&#…...

解密并下载受DRM保护的MPD(DASH流媒体)加密视频

要解密并下载受DRM保护的MPD&#xff08;DASH流媒体&#xff09;加密视频&#xff0c;需结合技术工具与合法授权。以下是关键方法与步骤&#xff1a; 一、工具与技术要求 Widevine-DL 这是一个开源Python工具&#xff0c;支持下载和解密Widevine DRM保护的MPD内容。它依赖ffmpe…...

数据可视化有哪些步骤?2025高效落地指南

分享大纲 1、科学框架&#xff1a;从数据到洞察落地 2、可视化实战&#xff1a;捷码快速搭建专业大屏 3、关键避坑指南 根据IBM研究&#xff0c;规范的数据可视化流程&#xff0c;可以使得数据可视化搭建效率提升41%。那有标准的数据可视化搭建方法是哪些呢&#xff1f;本文将借…...

Deepfashion2 数据集使用笔记

目录 数据类别: 筛选类别数据: 验证精度筛选前2个类别: 提取类别数据 可视化类别数据: Deepfashion2 的解压码 旋转数据增强 数据类别: 类别含义: Class idx类别名称英文名称0短上衣short sleeve top1长上衣long sleeve top2短外套short sleeve outwear3长外套lo…...

Dify知识库下载小程序

一、Dify配置 1.查看或创建知识库的API 二、下载程序配置 1. 安装依赖resquirements.txt ######requirements.txt##### flask2.3.3 psycopg2-binary2.9.9 requests2.31.0 python-dotenv1.0.0#####安装依赖 pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.…...

匀速旋转动画的终极对决:requestAnimationFrame vs CSS Animation

引言&#xff1a;旋转动画的隐藏陷阱 在现代Web开发中&#xff0c;实现一个流畅的无限旋转动画似乎是个简单任务。但当我深入探究时&#xff0c;发现这个看似基础的需求背后隐藏着性能陷阱、数学精度问题和浏览器渲染机制的深层奥秘。本文将带你从一段常见的requestAnimationF…...

数据库中求最小函数依赖集-最后附解题过程

今天来攻克数据库设计里一个超重要的知识点 —— 最小函数依赖集。对于刚接触数据库的小白来说&#xff0c;这概念可能有点绕&#xff0c;但别担心&#xff0c;咱们一步步拆解&#xff0c;轻松搞定&#x1f4aa;&#xff01; &#xff08;最后fuyou&#xff09; 什么是最小函数…...

嵌入式系统中常用的开源协议

目录 1、GNU通用公共许可证&#xff08;GPL&#xff09; 2、GNU宽松通用公共许可证&#xff08;LGPL&#xff09; 3、MIT许可证 4、Apache许可证2.0 5、BSD许可证 6、如何选择合适的协议 在嵌入式系统开发中&#xff0c;开源软件的使用已成为主流趋势。从物联网设备到汽车…...

MySQL 索引底层原理剖析:B+ 树结构、索引创建维护与性能优化策略全解读

引言 在 MySQL 数据库的世界里&#xff0c;索引是提升查询性能的关键利器。然而&#xff0c;很多开发者虽然知道索引的重要性&#xff0c;但对于索引背后的底层原理却知之甚少。本文将深入 MySQL 索引的底层实现&#xff0c;剖析 B 树的结构特点&#xff0c;以及如何利用这些知…...