Tokio中hang死所有worker的方法

tokio[1] 的 task (一个 future ) 里如果使用了阻塞调用,例如 std::mutex,会阻塞当前的 tokio-worker 线程,这个 worker 无法再执行其他 task。所以代码里如果不可避免的有(少量的)阻塞调用,就要为 runtime 启动更多的 worker 线程,保证存在没被阻塞的 worker 来执行待调度的 task,以避免整个 tokio runtime 完全 hang 住(有 task 但没 worker 运行它)。
但现实是,就算 worker 再多,tokio 也可能造成永久性的阻塞。
原因是 tokio 里的待执行 task 不是简单的放到一个 queue 里,除了 runtime 内共享的,可被每个 worker 消费的run_queue[2],每个 worker 还有一个自己的 lifo_slot[3],只存储一个最后被放入的 task (目的是减小调度延迟)。lifo_slot 只由它所属的 worker 使用,里面存储的 task 不能被其他 worker 执行。由于这个结构,构造 hang 住的方法是如图所示:
• future f1 被 runtime-1 执行, 持有一个 async 的锁 m 后,返回了 pending ,这时它被调度到 worker-1 本地的 lifo_slot。
• future f2 在 runtime-1 执行后返回 pending,被放入共享队列 run_queue。
• future f3 在 runtime-1 中执行, 它将一个任务 f4 交给其他的 runtime 去完成(例如为了隔离网络io和本地磁盘io),使用 block_on(f4)[4] 的方式,等待执行结果返回。
• f4 中也需要锁 m,等待。
这时,f2 在共享队列 run_queue 中,可以被执行,但是 f1 在 worker-1 本地的 lifo_slot 里,只能由 worker-1 调度,但 worker-1 当前阻塞在 f3。于是等待关系形成了一个环: f4 → m(f1) → f3 → f4,hang 死任务达成。


电动汽车电池导电涂层应用及现状
高精度、高稳定、耐高温晶体振荡器的意义
零跑与中国汽车流通协会签署战略合作协议,汽车销售模式正式公布
我国轮胎外胎产量波动起伏,轮胎行业需求量持续下滑
电梯行业这的六大问题,事关大家的乘梯安全
Tokio中hang死所有worker的方法
胆机六大故障及修理方法
硬件风向标:无人机时代真的来了吗?
基于C167CR微处理器实现汽车TCS硬件在环仿真系统的设计
柔性振动盘的简单介绍
传感器的作用
收音机电路中电阻器的作用是什么?
NVIDIA助力文远知行加速自动驾驶商业化应用进程
USB接口需要怎样的“保护伞”?WAYON维安负载开关给你答案
JY-LDE系列污水电磁流量计的特点
多通道农药残留速测仪的产品特点
这款创意灯白天隐身 夜晚发光
沃尔沃新汽车安全技术发布
利用小型气象站研究各种自然灾害
最新《人工智能报告》展望中美俄三国AI策略和发展前景