多线程编程技术解析及示例: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 错误码,避免因获取锁失败而直接进入临界区引发的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82456.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

元胞自动机(Cellular Automata, CA)

一、什么是元胞自动机&#xff08;Cellular Automata, CA&#xff09; 元胞自动机&#xff08;CA&#xff09; 是一种基于离散时间、离散空间与规则驱动演化的动力系统&#xff0c;由 冯诺依曼&#xff08;John von Neumann&#xff09; 于1940年代首次提出&#xff0c;用于模…

Flutter面试题

Flutter架构解析 1. Flutter 是什么?它与其他移动开发框架有什么不同? Flutter 是 Google 开发的开源移动应用开发框架,可用于快速构建高性能、高保真的移动应用(iOS 和 Android),也支持 Web、桌面和嵌入式设备。。它与其他移动开发框架(如 React Native、Xamarin、原…

MySQL 如何判断某个表中是否存在某个字段

在MySQL中&#xff0c;判断某个表中是否存在某个字段&#xff0c;可以通过查询系统数据库 INFORMATION_SCHEMA.COLUMNS 实现。以下是详细步骤和示例&#xff1a; 方法&#xff1a;使用 INFORMATION_SCHEMA.COLUMNS 通过查询系统元数据表 COLUMNS&#xff0c;检查目标字段是否存…

golang 实现基于redis的并行流量控制(计数锁)

在业务开发中&#xff0c;有时需要对某个操作在整个集群中限制并发度&#xff0c;例如限制大模型对话的并行数。基于redis zset实现计数锁&#xff0c;做个笔记。 关键词&#xff1a;并行流量控制、计数锁 package redisutilimport ("context""fmt""…

从线性方程组角度理解公式 s=n−r(3E−A)

从线性方程组角度理解公式 sn−r(3E−A) 这个公式本质上是 ​齐次线性方程组解空间维度 的直接体现。下面通过三个关键步骤解释其在线性方程组中的含义&#xff1a; 1. ​公式对应的线性方程组 考虑矩阵方程&#xff1a; (3E−A)x0 其中&#xff1a; x 是 n 维未知向量3E−…

Docker 在 AI 开发中的实践:GPU 支持与深度学习环境的容器化

人工智能(AI)和机器学习(ML),特别是深度学习,正以前所未有的速度发展。然而,AI 模型的开发和部署并非易事。开发者常常面临复杂的依赖管理(如 Python 版本、TensorFlow/PyTorch 版本、CUDA、cuDNN)、异构硬件(CPU 和 GPU)支持以及环境复现困难等痛点。这些挑战严重阻…

解决CSDN等网站访问不了的问题

原文网址&#xff1a;解决CSDN等网站访问不了的问题-CSDN博客 简介 本文介绍解决CSDN等网站访问不了的方法。 问题描述 CSDN访问不了了&#xff0c;页面是空的。 问题解决 方案1&#xff1a;修改DNS 可能是dns的问题&#xff0c;需要重新配置。 国内常用的dns是&#x…

使用tortoisegit连接远程仓库进行克隆、拉取、获取、提交、推送、新建/切换分支、重命名、删除的一套流程(附带巨全面的git命令)

1.整备好tortoisegit工具。 2.新建一个文件夹&#xff0c;并进入这个文件夹后鼠标右击&#xff08;选择克隆&#xff09;&#xff1a; 3.先去项目中拿到https地址&#xff0c;再填入&#xff1a; 4.新建分支&#xff0c;右击克隆到本地的项目文件&#xff1a; 5.推送到远程&am…

ArcGIS Pro 3.4 二次开发 - 地图创作 1

环境:ArcGIS Pro SDK 3.4 + .NET 8 文章目录 ArcGIS Pro 3.4 二次开发 - 地图创作 11 样式管理1.1 如何通过名称获取项目中的样式1.2 如何创建新样式1.3 如何向项目添加样式1.4 如何从项目中移除样式1.5 如何向样式添加样式项1.6 如何从样式中移除样式项1.7 如何判断样式是否可…

Express 集成Sequelize+Sqlite3 默认开启WAL 进程间通信 Conf 打包成可执行 exe 文件

代码&#xff1a;express-exe: 将Express开发的js打包成exe服务丢给客户端使用 实现目标 Express 集成 Sequelize 操作 Sqlite3 数据库&#xff1b; 启动 Sqlite3 时默认开启 WAL 模式&#xff0c;避免读写互锁&#xff0c;支持并发读&#xff1b; 利用 Conf 实现主进程与 Ex…

.Net Framework 4/C# 初识 C#

一、C# 专栏 由于博主原先是做的Linux C/C 嵌入式领域&#xff0c;因此对 C# 也较为懵懂&#xff0c;C# 是典型的 OOP 编程&#xff0c;这一点与 C 类似&#xff0c;但是在语法上&#xff0c;C# 移除了对指针的运用以及内存管理&#xff0c;所以既不用考虑指针的复杂运用也不用…

Python趣学篇:Pygame实现粒子烟花绽放效果

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《Python星球日记》🪐 目录 一、项目亮点与效果预览1. 核心特色功能2. 技术学习价值二、技术原理深度解析1. 向量运算:烟花运动的数学基…

NiceGUI 是一个基于 Python 的现代 Web 应用框架

NiceGUI 是一个基于 Python 的现代 Web 应用框架&#xff0c;它允许开发者直接使用 Python 构建交互式 Web 界面&#xff0c;而无需编写前端代码。以下是 NiceGUI 的主要功能和特点&#xff1a; 核心功能 1.简单易用的 UI 组件 提供按钮、文本框、下拉菜单、滑块、图表等常见…

Linux中的mysql逻辑备份与恢复

一、安装mysql社区服务 二、数据库的介绍 三、备份类型和备份工具 一、安装mysql社区服务 这是小编自己写的&#xff0c;没有安装的去看看 Linux换源以及yum安装nginx和mysql-CSDN博客 二、数据库的介绍 2.1 数据库的组成 数据库是一堆物理文件的集合&#xff0c;主要包括…

鸿蒙UI开发——组件的自适应拉伸

1、概 述 针对常见的开发场景&#xff0c;ArkUI开发框架提供了非常多的自适应布局能力&#xff0c;这些布局可以独立使用&#xff0c;也可多种布局叠加使用。本文针对ArkUI提供的拉伸能力做简单讨论。 拉伸能力是指容器组件尺寸发生变化时&#xff0c;增加或减小的空间全部分…

K 值选对,准确率翻倍:KNN 算法调参的黄金法则

目录 一、背景介绍 二、KNN 算法原理 2.1 核心思想 2.2 距离度量方法 2.3 算法流程 2.4算法结构&#xff1a; 三、KNN 算法代码实现 3.1 基于 Scikit-learn 的简单实现 3.2 手动实现 KNN&#xff08;自定义代码&#xff09; 四、K 值选择与可视化分析 4.1 K 值对分类…

Azure DevOps Server 2022.2 补丁(Patch 5)

微软Azure DevOps Server的产品组在4月8日发布了2022.2 的第5个补丁。下载路径为&#xff1a;https://aka.ms/devops2022.2patch5 这个补丁的主要功能是修改了代理(Agent)二进制安装文件的下载路径&#xff1b;之前&#xff0c;微软使用这个CND(域名为vstsagentpackage.azuree…

PHP7+MySQL5.6 查立得轻量级公交查询系统

# PHP7MySQL5.6 查立得轻量级公交查询系统 ## 系统简介 本系统是一个基于PHP7和MySQL5.6的轻量级公交查询系统(40KB级)&#xff0c;支持线路查询、站点查询和换乘查询功能。系统采用原生PHPMySQL开发&#xff0c;无需第三方框架&#xff0c;适合手机端访问。 首发版本&#x…

Vue-Cropper:全面掌握图片裁剪组件

Vue-Cropper 完全学习指南&#xff1a;Vue图片裁剪组件 &#x1f3af; 什么是 Vue-Cropper&#xff1f; Vue-Cropper 是一个简单易用的Vue图片裁剪组件&#xff0c;支持Vue2和Vue3。它提供了丰富的配置选项和回调方法&#xff0c;可以满足各种图片裁剪需求。 &#x1f31f; …

[Go] Option选项设计模式 — — 编程方式基础入门

[Go] Option选项设计模式 — — 编程方式基础入门 全部代码地址&#xff0c;欢迎⭐️ Github&#xff1a;https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-option 1 介绍 在 Go 开发中&#xff0c;我们经常遇到需要处理多参数配置的场景。传统方…