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

369_C++_pthread_cond_timedwait 超时阻塞,必须先初始化绑定CLOCK_MONOTONIC 一下,显式设置时钟类型才能使得超时阻塞生效 默认情况下,pthread_cond_timedwait 使用 CLOCK_REALTIME 作为时钟源,这意味着超时会根据系统的实时时间(即当前时间)来计算。而如果系统时间发生跳变(例如,NTP 校时或手动修改系统时间),可能会影响计算出的超时时间,导致超时行为不符合预期 阅读详情

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

别再死记硬背了!用MaxDEA软件实操SBM、DDF、NDDF模型,手把手教你测算绿色全要素生产率 本文深度解析如何使用MaxDEA软件实操SBM、DDF、NDDF模型,手把手教你测算绿色全要素生产率(GTFP)。通过详细的模型选择对比、数据准备策略和MaxDEA操作流程,帮助研究者科学构建指标体系并准确解读结果,提升环境管理研究的实证分析能力。 阅读详情

相关推荐

TDISP(TEE Device Interface Security Protocol)软件操作流程

/ 1. SPDM会话相关定义(🔶1-37、🔶1-187)// SPDM会话ID// AES-256-GCM加密密钥(TDISP要求)// 初始向量// 会话是否激活// 2. IDE流配置(🔶1-52、🔶1-625)// IDE流ID// 4个子流的AES密钥(覆盖所有子流类型)// 密钥是否已配置// 3. TDI状态与配置(🔶1-207、🔶1-210)TDI_CONFIG_UNLOCKED = 0, // 初始配置态。

inquisiter 1432

C/C++:pthread_cond_timedwait阻塞失败(立刻超时返回)

C/C++:pthread_cond_timedwait阻塞失败(立刻超时返回)

test1280 6620

FPGA矩阵键盘计算器Verilog实现与Quartus仿真全流程解析

本文详细解析了基于FPGA和Verilog的矩阵键盘计算器实现全流程,包括矩阵键盘扫描、状态机设计、算术运算逻辑及数码管显示驱动。通过Quartus仿真与Testbench测试,确保设计稳定性与准确性,适合数字逻辑设计初学者学习FPGA开发与硬件描述语言应用。

chair的专栏 742

线程死锁的代码示例

#include <cstddef> #include <cstdio> #include<iostream> #include<pthread.h> #include <unistd.h> using namespace std; /* 死锁:两个线程视图同时占用两个资源,并按不同的次序锁定相应的共享资源 解决方法: 按相同的次序锁定相应的共享资源 使用 pthread_.

青海蓝田的博客 954

不到200块!手把手教你用ZYNQ7010和AD9363攒一台自己的开源SDR硬件(附BOM清单)

本文详细介绍了如何用不到200元的预算,基于ZYNQ7010 FPGA和AD9363射频芯片打造一台功能完备的开源SDR硬件平台。从核心组件选型、PCB设计到焊接调试,提供全流程实战指南,特别适合预算有限的硬件爱好者和创客群体探索无线通信世界。

weixin_26854829的博客 479

STM32 伺服电机 指令脉冲+方向位置控制模式 主从定时器 实现PWM脉冲数精确控制

实验室有个项目涉及到多个步进电机以及伺服电机的控制,需要电机得到一个触发信号后精确移动一段距离。 下面以单个伺服电机控制为例,利用伺服电机的指令脉冲加方向位置控制模式实现jing'que ...

phcdd的博客 2万+

pthread_cond_timedwait函数使用

1 函数原型 #include <pthread.h> 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,

专注嵌入式领域 3万+

超越音频!STM32 SAI接口在AD7768高速ADC采集中的妙用(含PCB布局指南)

本文深入探讨了如何将STM32的SAI接口应用于AD7768高速ADC的数据采集系统,超越了其传统的音频应用范畴。文章详细解析了SAI协议与ADC时序的匹配方法,提供了从CubeMX配置、DMA数据搬运到关键PCB布局指南的完整实战方案,旨在帮助工程师实现稳定、高精度的工业级高速数据采集。

efc12345678的博客 304

pthread_mutex_trylock使用

pthread_mutex_trylock() 是 pthread_mutex_lock() 的非阻塞版本。如果被其他线程使用,返回其他值;如果没有被其他线程使用,那么进行加锁,并且返回0。所以可以通过这个判断是不是使用这这个锁,而不需要等待,提高实时性。

weixin_43614459的博客 627

Halcon和C#联合编程实现硬币识别(个人入门练习)

本人为机器视觉入门小白,自己突发奇想 1.图片数据来源和分析 2.HALCON实现 3.C#搭建界面框架 4.C#中嵌入HALCON代码,即联合编程 5.导出.exe文件,运行以及Debug 目标是这样的,在图片中识别出每种类型的硬币数量,然后计算出总钱数。先上结果,再细说过程。 C#界面和识别结果: 1.图片数据来源和分析 图片大小及格式均统一,拍摄的时候已经尽可能的去除了背景噪点,所以图像处理的要求并不很高(重点在于思路)。硬币区分原理本人代码采用直径范围来判断(也可以半径或区域面积,HALCON算子

Demobird的博客 3616

空天大模型详解

空天大模型是指面向空天信息领域(如卫星遥感、导航、气象等)设计的多模态人工智能模型,能够处理海量遥感数据、多传感器信息及跨时空分析任务。多模态融合:整合可见光、雷达、热红外、多光谱等多源遥感数据,构建统一表征空间,例如“空天·灵眸”3.0版支持航空、卫星及无人机数据的自动化解译。轻量化与高效推理:针对星载计算场景,采用分层量化、跨模态蒸馏技术压缩模型参数(如JigonGPT从1.02B压缩至0.23B,性能仅牺牲5.2%)18,并通过热传导架构提升计算速度2.4倍。神经符号结合。

zxy98的专栏 1569

Linux Pthread多线程编程:从基础概念到线程安全队列实战

多线程编程是现代软件开发中提升程序并发性能的核心技术,它允许程序同时执行多个任务,充分利用多核CPU的计算能力。其基本原理是通过创建多个独立的执行流(线程),共享进程的内存空间,从而实现数据的高效共享与通信。在Linux环境下,POSIX线程(Pthread)是实现多线程编程的C语言标准库,它提供了线程创建、同步、销毁等底层原语,是构建高性能服务器、并行计算和实时系统的技术基石。理解Pthread的互斥锁(mutex)和条件变量(cond)等同步机制,对于避免数据竞争和死锁至关重要,这直接关系到程序的正确性

weixin_34021089的博客 341

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

互斥锁和条件变量总结&接口介绍【pthread_mutex_init/lock/trylock/unlock/destroy】【pthread_cond_init/wait/timedwait/..】

文章目录0 - 前言1 - 互斥锁1-1 初始化锁1-2 加锁1-3 解锁1-4 销毁锁2 - 条件变量2-1 初始化条件变量2-2 等待条件变量2-3 唤醒线程2-4 销毁条件变量 0 - 前言 本文主要总结互斥锁和条件变量的关键接口 参考: C语言技术网-线程同步 条件变量 1 - 互斥锁 互斥锁时对于互斥资源(也叫临界资源)来说的,比如说有一个公共账户,有很多人都想对这个账户进行操作(存钱、取钱),为了保护账户操作的稳定,使用一种保障机制来保证同一时刻只有一个人操作账户。这种保障机制就是互斥锁。

日月既往,不可复追 626

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

#多线程编程

互斥锁常用来防止多个进程或线程同时访问相同的共享资源而导致的资源竞争。 互斥锁可以保证以下三点: 原子性:保证当某个线程锁定了一个互斥锁,其他线程不可能在同时能锁定该互斥锁。 唯一性:保证当某个线程已经锁定一个互斥锁时,在它解锁前,其他线程不可能锁定该互斥锁 非繁忙等待:保证当某个线程已经锁定一个互斥锁时,第二个线程又试图去锁定这个互斥锁,则第二个线程将被挂起。 API头文件 pthread.h创

哪吒要结婚的博客 365

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Linux并发编程:条件变量、信号量与生产者-消费者模型实战

并发编程是现代计算机系统的核心概念,通过多线程协作和进程通信实现资源的高效利用。其底层原理主要依赖同步机制如条件变量和信号量,前者解决线程间状态通知问题,后者控制资源访问并发度。这些技术在工程实践中具有重要价值,尤其在高性能服务器、物联网网关等场景中,能有效解决资源竞争和线程调度问题。以生产者-消费者模型为例,结合条件变量可实现高效的任务队列,而信号量则适用于连接池管理等场景。通过合理运用这些同步原语,开发者可以构建出既稳定又高效的并发系统,如文中提到的数据采集系统优化案例,显著提升了吞吐量和可靠性。

weixin_34396103的博客 360

Linux——线程

线程是进程内部的执行流,是CPU调度的基本单元,在Linux中本质上是轻量级的task_struct(PCB)。与进程相比,线程资源消耗更低、切换成本更低,且线程间通信更高效。线程间共享进程ID、虚拟地址空间等资源,但独有线程ID、栈空间等。Linux通过pthread库控制线程,包括创建(pthread_create)、退出(pthread_exit或pthread_cancel)、等待(pthread_join)和分离(pthread_detach)。线程安全需通过互斥(锁)和同步(条件变量、信号

炘爚的博客 271

linux线程同步和竞争

同步和互斥

TheoryGo的博客 85

unix环境高级编程=线程

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> *{padding: 0px;margin: 0px;} ul { list-style: none; width: 600px; border: 1px solid red; margin: 1

qq_37805832的博客 606

互斥锁和条件变量

1、互斥锁 互斥锁API pthread_mutex_lock(pthread_mutex_t *mutex); 用此函数加锁时,如果mutex已经被锁住,当前尝试加锁的线程就会阻塞,直到互斥锁被其他线程释放。当此函数返回时,说明互斥锁已经被当前线程成功加锁. pthread_mutex_trylock(pthread_mutex_t *mutex); ...

weixin_30477797的博客 132

Linux线程同步实战:互斥锁、信号量与条件变量详解

在并发编程中,线程同步是确保多线程安全访问共享资源的核心机制。其基本原理是通过协调线程执行顺序,防止数据竞争和状态不一致。从技术价值看,有效的同步能提升程序健壮性、避免竞态条件,并充分利用多核性能。常见的应用场景包括服务器开发、数据库连接池管理以及任务队列处理。本文聚焦于Linux环境下三种关键同步工具:互斥锁用于保护临界区,实现独占访问;信号量作为资源计数器,管理多资源池;条件变量则结合互斥锁实现高效等待通知机制。通过生产者-消费者模型等实战案例,深入解析如何组合使用这些工具解决实际并发问题,并涵盖死锁预

weixin_30788239的博客 410

线程同步学习笔记

其余的消费者线程由于没有抢到互斥锁,因此被阻塞在互斥锁上。当线程调用这个函数,并且sem中的资源数>0,线程不会阻塞,线程会占用sem中的一个资源,因此资源数-1,直到sem中的资源数减为0时,资源被耗尽,线程被阻塞,当阻塞指定的时长之后,线程解除阻塞。当线程调用这个函数,并且sem中的资源数>0,线程不会阻塞,线程会占用sem中的一个资源,因此资源数-1,直到sem中的资源数减为0时,资源被耗尽,但是线程不会被阻塞,直接返回错误号,因此可以在程序中添加判断分支,用于处理获取资源失败之后的情况。

丰锋的博客 196

Linux学习笔记(系统编程)

本笔记用于Linux个人陌生知识点查阅,内容并不详细完整,请见谅。

qq_56632135的博客 783

线程同步

线程同步 互斥锁mutex 锁类型 初始化方式 加解锁特征 调度特征 普通锁 PTHREAD_MUTEX_TIMED_NP PTHREAD_MUTEX_INITIALIZER 同一线程可重复加锁,解锁一次释放锁 先等待锁的进程先获得锁 嵌套锁 PTHREAD_MU...

weixin_30852419的博客 92

系统api-同步与互斥

同步,互斥,条件变量

x13262608581的博客 234

互斥量和条件变量的区别

互斥量与条件变量的区别 转载自:http://www.360doc.com/content/12/0129/10/1317564_182456205.shtml 前面谈过了线程锁,下面我们在继续研究一下线程锁; 互斥量从本质上来说是一个锁,对互斥量加锁后任何其他试图给它加锁的线程都会被阻塞直至当前线程释放互斥量。 同样在设计时需要规定所有的线程必须遵守相同的数据访问规则,只有这样互斥机...

weixin_34072857的博客 231

条件变量

条件变量采用等待唤醒的机制处理线程同步问题。不同于锁的机制,在判断需要等待满足条件才能执行的任务是,不需要不断的加锁,查询,判断,解锁的过程,从而减轻了CPU负担。 条件变量一般和互斥量配合使用,互斥量用于上锁,而条件变量用于事件的等待。 条件变量会在进入等待时释放互斥量,进行解锁操作,并且该线程进入睡眠状态。直到有其他线程发送信号,唤醒该等待线程,等待成功。一旦等待成功,则重新获取互斥量,进...

abe.yue的博客 173
上一篇: Playwright定位器详解:自动化测试的核心工具
下一篇: MCP Resource模块详解
未来创世纪
博客等级 码龄18年 960粉丝 209原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值