多线程之线程创建与管理:面试官问“机器人系统为什么必须用多线程”
从今天开始进入多线程板块。这块内容在C面试里分量很重——互斥锁、死锁、条件变量、原子操作、线程池一连串的话题每个都能聊一篇。先从最基础的开始线程的创建与管理。为什么要用多线程这个问题在机器人开发里答案特别明确因为你的系统有多个独立的任务必须同时运行。想象一下一台自主导航的机器人需要同时做这些事读取激光雷达数据10Hz、读取IMU数据200Hz、运行SLAM算法5Hz、执行路径规划2Hz、发送电机控制指令50Hz。这些任务的频率不一样逻辑完全独立但必须同时跑。如果你用单线程串行执行一个任务卡住了其他任务全停——机器人就会在原地发呆然后撞上墙。C11线程的基本用法C11之前写线程得用平台相关的API——Linux用pthreadWindows用CreateThread。C11统一了接口用std::thread就行了。#include thread #include iostream void lidarTask() { while (true) { auto scan readLidar(); processScan(scan); this_thread::sleep_for(100ms); // 10Hz } } void imuTask() { while (true) { auto data readIMU(); updateOdometry(data); this_thread::sleep_for(5ms); // 200Hz } } int main() { thread t1(lidarTask); thread t2(imuTask); t1.join(); // 等待线程结束 t2.join(); return 0; }几个要注意的点thread对象创建之后线程就已经开始运行了。你必须选择join等待线程结束或者detach让线程独立运行。如果你什么都不做就销毁thread对象程序会直接abort——这是C11的硬性规定。void example() { thread t(someTask); // 如果这里抛异常t被销毁时没有join或detach程序崩溃 } // 安全的做法用RAII包装 class ScopedThread { thread t_; public: explicit ScopedThread(thread t) : t_(std::move(t)) {} ~ScopedThread() { if (t_.joinable()) t_.join(); } ScopedThread(const ScopedThread) delete; ScopedThread operator(const ScopedThread) delete; }; void safeExample() { ScopedThread t(thread(someTask)); // 即使抛异常析构函数也会join }给线程传参数thread的构造函数可以接受参数传给线程函数void sensorTask(const string sensorName, int frequency) { cout sensorName running at frequency Hz endl; // ... } thread t1(sensorTask, lidar, 10); thread t2(sensorTask, imu, 200);这里有个坑参数默认是按值拷贝传递的。如果你想传引用必须用std::refvoid processData(vectorfloat data) { // 修改data } vectorfloat sensorData; // thread t(processData, sensorData); // 错这是拷贝 thread t(processData, std::ref(sensorData)); // 对传引用机器人系统中的线程架构实际项目里线程的组织方式通常有两种。第一种是每任务一线程每个独立的任务有自己的线程。简单直接但线程多了之后管理困难。class RobotSystem { thread lidarThread_, imuThread_, plannerThread_, controllerThread_; public: void start() { lidarThread_ thread(RobotSystem::lidarLoop, this); imuThread_ thread(RobotSystem::imuLoop, this); plannerThread_ thread(RobotSystem::plannerLoop, this); controllerThread_ thread(RobotSystem::controllerLoop, this); } void stop() { running_ false; lidarThread_.join(); imuThread_.join(); plannerThread_.join(); controllerThread_.join(); } };第二种是线程池创建固定数量的线程把任务丢到队列里让线程池调度。下篇会详细讲这个。ROS2用的是第一种方式的变体——每个回调函数在自己的线程里执行。ROS2的executor负责管理这些线程把回调分发到对应的线程上。线程的生命周期管理创建线程容易管理难。几个实际问题怎么让线程停下来不能直接杀死一个线程C没有这个功能。正确做法是设一个标志位线程循环里检查这个标志atomicbool running_{true}; void sensorLoop() { while (running_) { auto data readSensor(); processData(data); } // 清理资源安全退出 } void stop() { running_ false; thread_.join(); // 等待线程退出 }怎么知道线程有没有正常启动可以在线程函数开头设一个ready标志主线程等待这个标志void workerLoop() { initResources(); ready_ true; // 通知主线程我准备好了 while (running_) { // 工作循环 } }面试中的关键考点thread和process有什么区别线程共享同一进程的内存空间进程有独立的地址空间。线程创建和切换的开销比进程小得多。但线程之间共享数据需要同步进程之间不需要但也意味着隔离性更好。join和detach有什么区别join会阻塞调用者直到目标线程执行完毕。detach让线程独立运行之后你没法再等它了。detach之后线程的资源在线程结束时由系统自动回收。一个进程最多能创建多少线程取决于系统资源。每个线程需要一定的栈空间Linux默认8MB所以理论上受限于虚拟地址空间。实际上创建几百到几千个线程是常见的。但线程太多会导致频繁的上下文切换反而降低性能。实战中还有一个很容易被忽视但非常实用的技巧给线程命名。在Linux下可以用pthread_setname_np给线程设置名字然后在top -H或者/proc/self/task/里就能看到每个线程的名字。在机器人系统里线程一多之后传感器采集线程、规划线程、控制线程、通信线程……用GDB调试时如果所有线程都显示为无名线程排查起来非常痛苦。给每个线程起个有意义的名字调试效率会大幅提升。面试时如果你能提到这种工程实践中的小技巧面试官会觉得你是一个有实战经验的开发者而不只是在课本上学的理论。给正在准备面试的你多线程的基础——创建线程、传参数、join/detach——这些是必须会写的。面试的时候面试官可能让你手写一个简单的多线程程序比如一个生产者消费者模型。但光会创建线程不够。线程之间的同步才是多线程的核心问题——数据竞争、死锁、条件等待。这些是后面几篇的内容。下篇聊互斥锁与死锁——一个真实死锁bug的排查过程。这是多线程编程里最容易踩的坑面试几乎必考。如果这篇文章对你有帮助欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。「机器人软件开发面试·从入门到精通」连载系列上一篇第53篇 零拷贝技术——大数据量传输的性能关键 下一篇预告第55篇 多线程之互斥锁与死锁——一个真实死锁bug的排查过程有任何问题欢迎评论区留言我会尽量回复。

相关新闻

2024年7月AI大模型技术报告:Gemini、Grok、GPT最新突破与编程模型格局

2024年7月AI大模型技术报告:Gemini、Grok、GPT最新突破与编程模型格局

最近在AI领域真是热闹非凡,各大厂商都在密集发布新模型和功能更新。如果你正在关注AI大模型的最新进展,特别是Gemini、Grok和GPT系列的最新动态,那么本文正好为你整理了一份完整的7月AI技术发展报告。本文将详细解析Gemini 3.5 Pro的发布预测…

2026/10/15 3:01:22 阅读更多 →
春晚机器人秀技术拆解:从多智能体协同到工程化落地挑战

春晚机器人秀技术拆解:从多智能体协同到工程化落地挑战

1. 从春晚舞台到技术巅峰:一场机器人秀背后的硬核拆解今年春晚,相信不少朋友和我一样,被一个瞬间“震”住了:一群形态各异的机器人,在舞台上整齐划一地起舞、奔跑,甚至完成高难度的后空翻。这个来自宇树科技…

2026/10/14 15:53:23 阅读更多 →
windows网络适配器驱动开发-移动宽带 (MBB) WDF 类扩展 (MBBCx)

windows网络适配器驱动开发-移动宽带 (MBB) WDF 类扩展 (MBBCx)

从下一个版本的 Windows 10 开始,Windows 驱动程序工具包 (WDK) 包括移动宽带 (MBB) WDF 类扩展,可与 NetAdapterCx 配合使用。 MBB-NetAdapter客户端驱动程序首先是完全完善的 WDF 客户端驱动程序,然后是 NetAdapterCx 客户端驱动程序&#…

2026/10/14 20:24:10 阅读更多 →

最新新闻

pQTLtools 安装全流程:R 版本、Bioconductor 与依赖配置避坑指南

pQTLtools 安装全流程:R 版本、Bioconductor 与依赖配置避坑指南

简介:pQTLtools 是一套面向蛋白质定量性状基因座(pQTL)研究的 R 语言工具包,适合从事遗传学、蛋白质组学与生物信息分析的科研人员及研究生使用,用于整合与处理 Olink、SomaLogic、Caprion 等主流蛋白质检测平台的数据…

2026/10/15 14:32:42 阅读更多 →
中细软GEO优化的优势是什么?

中细软GEO优化的优势是什么?

中细软GEO是港股上市公司中细软集团旗下(01020.HK)的AI获客优化服务,通过系统性优化企业信息资产,让品牌在AI回答中被理解、引用并优先推荐。 当用户在豆包、DeepSeek、腾讯元宝、文心一言、通义千问里问“哪家工厂能做某类产品”…

2026/10/15 14:32:42 阅读更多 →
张雪峰推荐!收藏这份网络安全学习指南,小白也能入门高薪赛道!

张雪峰推荐!收藏这份网络安全学习指南,小白也能入门高薪赛道!

张雪峰推荐!收藏这份网络安全学习指南,小白也能入门高薪赛道! 本文分析了张雪峰推荐网络安全专业的原因,指出行业存在巨大人才缺口和政策支持,薪资水平较高且职业发展路径多样。文章强调实战能力的重要性,…

2026/10/15 14:32:42 阅读更多 →
Android天气App实战:百度地图定位与和风天气API集成及折线图展示

Android天气App实战:百度地图定位与和风天气API集成及折线图展示

1. 这个天气App到底解决了什么问题刚接触Android开发的朋友,十有八九都是从“做一个天气App”开始的。原因很简单:它足够小,小到一个周末就能跑通;又足够全,全到能把网络请求、数据解析、UI渲染、权限管理这些核心环节…

2026/10/15 14:32:42 阅读更多 →
Windows Server 2012 R2 离线安装 IIS 完整指南:DISM 命令与避坑

Windows Server 2012 R2 离线安装 IIS 完整指南:DISM 命令与避坑

简介:这份离线安装包面向需要在无外网环境下为 Windows Server 2012 R2 部署或更新 IIS 的 IT 运维人员与系统管理员,解决内网、隔离网段或严格安全策略下无法在线获取系统组件的问题。压缩包共 1568 个文件,约 99.04MB,以 dll、r…

2026/10/15 14:32:42 阅读更多 →
OpenShell:面向开发者的Windows桌面增强工具

OpenShell:面向开发者的Windows桌面增强工具

1. OpenShell 是什么?它不是 Shell,更不是“开源外壳” OpenShell 这个名字,乍一听容易让人误以为是某种 Linux 或 macOS 的 shell 替代品——比如像 zsh、fish 那样的命令行解释器,或者某个带图形界面的终端模拟器。但事实恰恰相…

2026/10/15 14:31:41 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 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/15 0:14:36 阅读更多 →
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/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练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/15 9:49:14 阅读更多 →