You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Ruby Fiber仅在设置调度器后才实现并发执行?

问题解答

核心结论

Ruby的Fiber本身是协作式流控制结构,但Ruby 3.0引入的Fiber调度器API赋予了它实现并发的能力——这就是你观察到两种执行结果差异的根本原因。早期Stack Overflow回答的结论针对的是3.0之前的Ruby版本,和当前特性不矛盾。


1. 未设置调度器时:Fiber串行执行

当你不指定调度器时,Fiber.resume会阻塞当前线程,直到该Fiber完全执行完毕才会继续执行后续代码。你的代码中:

  • 每个Fiber里的sleep 1是Ruby默认的阻塞式sleep,它不会主动触发Fiber让出控制权。
  • 第一个Fiber跑完1秒sleep后,第二个Fiber才会被resume,以此类推,5个Fiber总共耗时约5秒。

对应的执行命令与输出:

time bundle exec ruby main.rb
Beginning calculation #1...
Beginning calculation #2...
Beginning calculation #3...
Beginning calculation #4...
Beginning calculation #5...
Finished all calculations!

real    0m5.179s
user    0m0.146s
sys     0m0.027s

2. 设置调度器后:Fiber并发执行

Ruby 3.0+的核心方法(包括sleep)都适配了Fiber调度器API:

  • 当检测到全局调度器(通过Fiber.set_scheduler设置)存在时,sleep会主动挂起当前Fiber,并通知调度器去调度其他已就绪的Fiber。
  • libev_scheduler是基于libev的事件驱动调度器,它会在一个Fiber挂起时立刻切换到另一个Fiber执行,因此5个Fiber的sleep 1是并行进行的,总耗时约1秒。

对应的执行命令与输出:

time bundle exec ruby main.rb --set-sched
Beginning calculation #1...
Beginning calculation #2...
Beginning calculation #3...
Beginning calculation #4...
Beginning calculation #5...
Finished all calculations!

real    0m1.173s
user    0m0.150s
sys     0m0.021s

3. 与早期回答的矛盾解释

早期Stack Overflow回答的结论针对的是Ruby 3.0之前的版本:那时没有Fiber调度器API,Fiber只能通过手动调用Fiber.yield和Fiber.resume实现流控制,无法自动处理阻塞操作来实现并发,所以说它是“流控制结构而非并发工具”是正确的。

而Ruby 3.0引入的调度器API,让Fiber可以结合事件驱动框架(比如libev_scheduler),自动在阻塞操作时让出控制权,从而实现协作式并发——这是Ruby版本迭代带来的新特性,和老回答的结论并不冲突。


你的理解验证

你的思路完全正确:Fiber是协作式并发,需要主动让出控制权才能实现并发。设置调度器后,sleep这类阻塞方法会自动触发Fiber挂起(相当于自动执行Fiber.yield),调度器负责切换到其他Fiber,最终实现了并发执行。


内容的提问来源于stack exchange,提问作者Matt Welke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 07:05:24