登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
导读
排行榜
资讯
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
写记录
写博客
小组
VIP申请
VIP网盘
网盘
联系我们
发帖说明
道具
勋章
任务
淘帖
动态
分享
留言板
导读
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
从源码角度解析C++20新特性如何简化线程超时取消 ...
从源码角度解析C++20新特性如何简化线程超时取消
[ 复制链接 ]
国语诗
3 小时前
程序园永久vip申请,500美金$,无限下载程序园所有程序/软件/数据/等
C++20中增加了很多重量级新特性,它不仅带来了ranges、concept和协程,也为多线程编程带来了jthread和stop_source这些强力辅助。利用这些新特性,我们可以更高效地编写并发程序。
今天要说的就是利用jthread和stop_source来简化线程超时控制的实现,最终我们可以实现一个简单高效、可维护性不输给号称“天生支持并发”的Go语言的版本。
为什么需要超时控制
超时控制是很常见的需求,最普遍的场景是为了防止程序卡住或者长时间占用资源,程序会主动取消掉一些超过允许运行时间的或者无响应的线程,比如一些耗时很长的网络连接处理线程等。当然用户等得不耐烦了手动点击取消任务执行也勉强可以算在内。
通常超时发生或者用户点击取消之后,我们都期待线程能迅速终止执行并让整个程序保持一个完整且安全的状态。然而现实是复杂的,想实现上述功能对于线程来说是一件难事,尤其在Linux系统上。
第一个难点是如何让线程知道自己要退出。对于进程来说这不是难点,因为不管进程在做什么,我们都可以靠向其发送信号来立即中断进程的执行(前提是线程没有屏蔽这个信号),这样进程的停止请求可以被立即感知到,进程从而可以尽快完成善后工作退出执行。同样的招数对多线程程序来说就没那么好用了——信号默认是发给整个进程的,为了能让每个线程独立地接收信号,我们需要保存线程的标识符并在每个线程中设置接收和屏蔽信号的mask,这大大增加了程序的复杂性;其次信号处理函数是整个进程内所有线程共享的,我们需要额外的手段来保证并发安全,同时还得兼顾信号处理函数需要可重入、快速执行的最佳实践,这会提高程序的开发难度。
第二个难点在于如何保证线程一定会退出执行。前面说到信号可以打断进程的执行,但这只是通知,实际上进程完全可以在信号处理函数返回后无视这个通知继续运行,或者有一种更普遍的场景——程序正好卡在某个系统调用上,而程序又设置了系统调用被信号中断后自动重启,这样即使我们有效通知了进程,进程也会在收完通知之后再次进入系统调用从而无法响应停止请求。所以作为保底手段,Linux可以发送SIGKILL这个信号强制终止进程,这个信号无法捕获也无法屏蔽,是我们货真价实的“底牌”。
上述的情况在多线程中同样存在,而且我们没有“底牌”可用——因为不管给哪个线程发送SIGKILL,都会杀死整个进程而不是单独接收到信号的那个线程。另外即使有办法强制终止线程(比如早期的JVM),我们还会遇到资源释放的问题。进程退出执行之后,内核会尽可能释放进程持有的所有资源,打开的文件会被关闭,缓冲区的内容会被刷新,文件锁之类的同步机制也会正常解锁;但线程并没有这种自动清理机制,清理工作完全需要手动执行,一旦进程没有释放自己持有的资源就退出,系统就会遇到各种数据损坏和死锁等并发问题,排查和修复会极其困难。
为了克服上述难点并安全高效地实现终止超时线程的执行,我们需要一些额外的控制手段。这也一直都是开发者中的热门话题。
在介绍C++20如何简化超时控制之前,我们先来看看前人的智慧成果。
Golang实现超时控制
Golang是天生支持并发的语言,这一点可谓名副其实,尤其是在超时控制上。
我们直接看个例子,例子里有主线程和工作线程,工作线程超时时间为5秒,如果超过这个时间还有线程没完成工作,就取消所有线程的执行。Golang里没有系统级的线程,但我们可以用goroutine模拟。
在工作线程中我们用sleep代替耗时的工作,这样便于测试:
[code]func Work(ctx context.Context, id int) error { for range 10 { select { case
源码
角度
解析
新特性
特性
相关帖子
C++ 原子操作解析
【节点】[RGBtoLuminance节点]原理解析与实际应用
【Agent】MemOS 源码笔记---(6)---MemScheduler -- 总体
【节点】[LinearToGammaSpaceExact节点]原理解析与实际应用
Flink源码阅读:如何生成JobGraph
Flink源码阅读:如何生成ExecutionGraph
【节点】[GammaToLinearSpaceExact节点]原理解析与实际应用
Lit 架构解析:从 Web Components 到 lit-html 的底层原理
【Agent】MemOS 源码笔记---(7)---MemScheduler 细节
Flink源码阅读:集群启动
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
业界
C++ 原子操作解析
2
627
庞悦
2025-12-18
安全
【节点】[RGBtoLuminance节点]原理解析与实际应用
1
453
趣侮
2025-12-18
业界
【Agent】MemOS 源码笔记---(6)---MemScheduler -- 总体
1
332
上官银柳
2025-12-18
安全
【节点】[LinearToGammaSpaceExact节点]原理解析与实际应用
0
165
欧阳梓蓓
2025-12-20
业界
Flink源码阅读:如何生成JobGraph
1
734
钨哄魁
2025-12-20
业界
Flink源码阅读:如何生成ExecutionGraph
0
762
唯棉坜
2025-12-21
安全
【节点】[GammaToLinearSpaceExact节点]原理解析与实际应用
0
872
欧阳雪枫
2025-12-22
业界
Lit 架构解析:从 Web Components 到 lit-html 的底层原理
0
934
威割
2025-12-22
业界
【Agent】MemOS 源码笔记---(7)---MemScheduler 细节
0
165
怀陶宁
2025-12-22
业界
Flink源码阅读:集群启动
0
599
锦惺
2025-12-23
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
国语诗
3 小时前
关注
0
粉丝关注
11
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
3934307807
991124
anyue1937
9994892
kk14977
6845358
4
xiangqian
638210
5
韶又彤
9997
6
宋子
9981
7
闰咄阅
9993
8
刎唇
9993
9
俞瑛瑶
9998
10
蓬森莉
9949
查看更多
今日好文热榜
239
STM32项目添加格外HAL库
194
MySQL 在哪些场景下不会写 binlog
311
从numpy数组等间距定长采样
877
经同意的语音克隆
522
具身智能:零基础入门睿尔曼机械臂(六)—
223
技术赋能・增长提速 —— 广州旗引科技专访
16
新品发布 | TestBase VCI 0620:新架构下高
699
从源码角度解析C++20新特性如何简化线程超
886
组合数学基础
833
C#/.NET/.NET Core技术前沿周刊 | 第 64 期
598
Flink源码阅读:集群启动
572
Unicode中如何表示未收录的生僻字 --浅谈ID
422
畅联云和智能物联中台UCC的关系
349
ROS2之URDF建模
223
MQ 选型框架——Kafka/RabbitMQ/RocketMQ
117
CoT论文阅读笔记
987
化整为零、分而治之、异步编排:一文读懂现
223
【Ubuntu】Ubuntu 22.04 与 Windows 跨系统
165
【Agent】MemOS 源码笔记---(7)---MemSched
988
XML中俩个String类型的比较却抛出NumberFor