嵌入式多线程开发:pthread 线程与互斥锁实战
嵌入式多线程开发pthread 线程与互斥锁实战一、引言上一篇文章我们讨论了fork多进程开发。进程固然好——每个进程独立地址空间崩溃不互相影响——但创建开销大、进程间通信IPC麻烦。在很多嵌入式场景中我们需要轻量级的并行这时多线程就登场了。线程Thread是共享同一进程地址空间的执行流。多个线程之间切换开销远小于进程切换而且可以直接访问同一块内存通信几乎零成本——但也正因如此必须用互斥锁等手段保护共享数据。本文从pthread的创建讲起深入互斥锁的原理与死锁排查最后给出一个传感器数据采集并发的实战模型。二、线程 vs 进程一张表看懂对比维度进程线程创建开销大分配独立地址空间小共享地址空间切换开销大切换页表小只切换寄存器和栈内存共享IPC 手段管道/共享内存天然共享全局变量和堆崩溃影响不影响其他进程一个线程崩溃可能拖垮整个进程适用场景隔离性要求高高并发、实时性要求高在嵌入式 Linux 中线程的优势尤为明显传感器线程、网络通信线程、数据处理线程可以各司其职互不阻塞。三、创建线程pthread_create#includepthread.hintpthread_create(pthread_t*thread,constpthread_attr_t*attr,void*(*start_routine)(void*),void*arg);看起来参数多拆解一下thread输出参数保存新线程的 IDattr线程属性NULL 表示默认start_routine线程入口函数必须是void* func(void* arg)签名arg传给入口函数的参数编译时需要链接 pthread 库gcc-oapp main.c-lpthread基础示例#includestdio.h#includepthread.h#includeunistd.hvoid*sensor_task(void*arg){intid*(int*)arg;for(inti0;i5;i){printf([传感器%d] 第%d次采样\n,id,i1);sleep(1);}printf([传感器%d] 采集结束\n,id);returnNULL;}intmain(void){pthread_ttid1,tid2;intid11,id22;pthread_create(tid1,NULL,sensor_task,id1);pthread_create(tid2,NULL,sensor_task,id2);// 主线程等待两个子线程结束pthread_join(tid1,NULL);pthread_join(tid2,NULL);printf(所有传感器采集完成\n);return0;}pthread_join会阻塞当前线程直到目标线程结束——类似于进程中的waitpid。四、互斥锁保护共享数据多线程同时访问同一变量时会出现竞态条件Race Condition。想象两个线程同时对counter操作线程A: 读 counter(0) → 加1(1) → 写 counter(1) 线程B: 读 counter(0) → 加1(1) → 写 counter(1)本应是 2结果却是 1——这就是数据竞争。解决方式是互斥锁Mutex。#includepthread.hpthread_mutex_tlockPTHREAD_MUTEX_INITIALIZER;intshared_counter0;void*worker(void*arg){for(inti0;i100000;i){pthread_mutex_lock(lock);// 加锁shared_counter;// 临界区pthread_mutex_unlock(lock);// 解锁}returnNULL;}互斥锁像厕所的锁——一个人进去了就锁门别人在外面等着。出来解锁后下一个人才能进去。互斥锁的四种操作函数行为pthread_mutex_lock阻塞等待直到拿到锁pthread_mutex_trylock立即返回拿不到锁返回 EBUSYpthread_mutex_unlock释放锁pthread_mutex_destroy销毁锁用动态方式创建的静态初始化用PTHREAD_MUTEX_INITIALIZER动态初始化用pthread_mutex_init。五、死锁当两把锁互相等待这是多线程编程中最让人头疼的问题。看这段代码pthread_mutex_tlockAPTHREAD_MUTEX_INITIALIZER;pthread_mutex_tlockBPTHREAD_MUTEX_INITIALIZER;// 线程1void*thread1(void*arg){pthread_mutex_lock(lockA);// 拿到 Asleep(1);// 给线程2时间去拿 Bpthread_mutex_lock(lockB);// 等待 B...// ...}// 线程2void*thread2(void*arg){pthread_mutex_lock(lockB);// 拿到 Bsleep(1);// 给线程1时间去拿 Apthread_mutex_lock(lockA);// 等待 A...// ...}结果线程1 持有 A 等 B线程2 持有 B 等 A——谁也等不到谁死锁。避免死锁的黄金法则固定加锁顺序所有线程必须按相同顺序获取多把锁限制锁粒度锁保护的代码越少越好使用pthread_mutex_trylock拿不到就放弃稍后重试超时机制部分 pthread 实现支持pthread_mutex_timedlock固定加锁顺序举例// 无论哪个线程都先锁 lockA 再锁 lockBpthread_mutex_lock(lockA);pthread_mutex_lock(lockB);// 临界区...pthread_mutex_unlock(lockB);pthread_mutex_unlock(lockA);六、实战传感器采集 线程池模型下面是一个简化版的多线程传感器采集架构#includestdio.h#includestdlib.h#includepthread.h#includeunistd.h#defineSENSOR_COUNT3pthread_mutex_tdata_lockPTHREAD_MUTEX_INITIALIZER;// 共享数据缓冲区typedefstruct{floattemperature;floathumidity;floatpressure;intupdated;}SensorData;SensorData g_data{0};void*temp_sensor(void*arg){(void)arg;while(1){pthread_mutex_lock(data_lock);g_data.temperature25.0(rand()%100)/10.0;g_data.updated1;pthread_mutex_unlock(data_lock);sleep(2);}returnNULL;}void*report_thread(void*arg){(void)arg;while(1){pthread_mutex_lock(data_lock);if(g_data.updated){printf([上报] 温度%.1f°C\n,g_data.temperature);g_data.updated0;}pthread_mutex_unlock(data_lock);sleep(3);}returnNULL;}intmain(void){pthread_tt1,t2;pthread_create(t1,NULL,temp_sensor,NULL);pthread_create(t2,NULL,report_thread,NULL);pthread_join(t1,NULL);pthread_join(t2,NULL);return0;}这个架构很简单但实用采集线程定时更新共享数据上报线程定时读取并上报靠互斥锁保证数据一致性。七、总结多线程编程的核心就三件事创建与回收pthread_create/pthread_join数据保护互斥锁pthread_mutex_lock/unlock死锁避免固定加锁顺序、减小锁粒度、用 trylock在嵌入式 Linux 中线程是并行处理的主力。掌握互斥锁你的程序才能在高并发下稳如磐石。

相关新闻

Light Tips项目入门:PHP开发者必学的基础算法与数据结构

Light Tips项目入门:PHP开发者必学的基础算法与数据结构

Light Tips项目入门:PHP开发者必学的基础算法与数据结构 【免费下载链接】light-tips Some code tips about algorithms, php and more 🔥 项目地址: https://gitcode.com/gh_mirrors/li/light-tips Light Tips是一个专为PHP开发者设计的算法与数…

2026/10/13 12:42:37 阅读更多 →
解锁飞行模式:INAV Configurator中10种飞行模式的设置与实战技巧

解锁飞行模式:INAV Configurator中10种飞行模式的设置与实战技巧

解锁飞行模式:INAV Configurator中10种飞行模式的设置与实战技巧 【免费下载链接】inav-configurator 项目地址: https://gitcode.com/gh_mirrors/in/inav-configurator INAV Configurator是一款强大的开源飞控配置工具,帮助无人机爱好者轻松设置…

2026/10/16 19:30:58 阅读更多 →
张家口本土经营世纪腾达实木门店众多,究竟哪家才是靠谱之选?

张家口本土经营世纪腾达实木门店众多,究竟哪家才是靠谱之选?

在张家口,实木家具市场呈现出一派热闹景象,世纪腾达实木家具更是备受消费者青睐。然而,面对众多经营世纪腾达实木的门店,消费者往往会感到困惑:究竟哪家才是靠谱之选呢?今天,我们就来深入剖析一…

2026/10/16 20:37:48 阅读更多 →

最新新闻

环境变量全攻略:从原理到实战,避开PATH与配置那些坑

环境变量全攻略:从原理到实战,避开PATH与配置那些坑

说实话,我见过太多人在环境变量上栽跟头了。明明代码逻辑一点问题没有,换台机器跑就报错,最后折腾半天发现是环境变量没配对。环境变量这东西,说简单,十分钟就能学会怎么用;说复杂,它能让你在深…

2026/10/17 4:02:00 阅读更多 →
RAG文档预处理实战:从解析到切分的完整链路

RAG文档预处理实战:从解析到切分的完整链路

1. 真正拖垮RAG的,往往是你最不在意的文档预处理环节这两年RAG(检索增强生成)几乎是个人知识库和企业知识中台项目的标配,很多人拿着一堆PDF、Word、Markdown就往向量库里灌。最开始跑demo很兴奋,查询响应快、答案也有…

2026/10/17 4:01:59 阅读更多 →
零基础上手 Claude Code:从安装到写出第一个本地脚本

零基础上手 Claude Code:从安装到写出第一个本地脚本

如果你和我一样,属于那种“平时不搞专业开发,但是经常有些小脚本、小工具的念头,想让电脑帮自己干点活”的人,那你一定经历过这种场景:脑子里有个特别清晰的功能,打开编辑器盯着屏幕,却一个字都…

2026/10/17 4:01:59 阅读更多 →
gocv图像预处理三要素:阈值分割、反色与边缘提取实战

gocv图像预处理三要素:阈值分割、反色与边缘提取实战

1. 这不是调色,是图像语义的第一次“断句”很多人第一次接触机器视觉项目时,会下意识把“阈值分割”“反色”“边缘提取”当成Photoshop里的滤镜操作——点几下鼠标,图变个样,任务就算完成。但实际在工业检测、医疗影像或自动驾驶…

2026/10/17 4:01:59 阅读更多 →
链表插入操作从原理到实战:头插、尾插、任意位置与哨兵节点

链表插入操作从原理到实战:头插、尾插、任意位置与哨兵节点

链表插入操作:从原理到实战的完整拆解如果你学过数据结构,大概率绕不开链表。链表这玩意儿,说难不难,说简单也不简单,尤其插入操作,无论笔试、面试还是实际项目,几乎场场必考。很多人背了代码就…

2026/10/17 4:01:59 阅读更多 →
ENVI插件实现朱文泉CASA模型植被NPP估算与Python趋势分析

ENVI插件实现朱文泉CASA模型植被NPP估算与Python趋势分析

简介:朱文泉植被NPP程序V2.0是面向遥感与生态研究者的ENVI扩展插件,用于净初级生产力(NPP)估算。相比旧版,它支持直接由日照时数计算太阳辐射、以NDVI的HDF格式生成时序NDVI,并可在模块内完成气象数据插值&…

2026/10/17 4:00:59 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →