PHP 8.1 的 Fibers 是用户态轻量级执行单元,非协程函数,需配合非阻塞 I/O 与事件循环实现异步;单纯使用 suspend/resume 仅支持协作式切换,无法替代底层异步 I/O 实现。

PHP 8.1 的 Fibers 不是“协程函数”,而是一套原生的、用户态的轻量级执行单元机制。它本身不直接实现异步 I/O,但为异步编程提供了底层调度能力——关键在于:Fiber 必须与非阻塞 I/O(如基于 epoll/kqueue 的 socket 操作)配合使用,才能真正达成异步效果。
核心逻辑:挂起 + 事件循环驱动
Fiber 无法自己检测网络就绪或文件读完,它靠的是“主动让出 + 外部调度”。典型流程是:
- 协程发起一个非阻塞 I/O 请求(例如调用 Swoole 的 co::sleep、co::read,或 ReactPHP 的 Promise-aware socket)
- 发现操作未立即完成,就调用 Fiber::suspend() 暂停自己,并把控制权交还给主事件循环
- 事件循环继续轮询其他任务或监听 I/O 就绪事件
- 当该 I/O 完成时,事件循环调用对应 Fiber 的 resume(),并可传入结果或异常
- Fiber 从 suspend() 返回处继续执行,就像同步代码一样拿到数据
为什么不能只用 Fiber 写纯异步?
单纯用 new Fiber(...) + suspend/resume 只能实现协作式多任务切换,但仍是同步阻塞风格——如果你在里面调用 file_get_contents() 或 mysqli_query(),整个线程仍会卡住。真正异步需要:
- 底层 I/O 必须是非阻塞的(如 libevent、ev、Swoole coroutines、Amp 的 loop)
- Fiber 是调度容器,不是 I/O 实现者;它把“等结果”这个动作变成可中断的语义
- PHP 标准库(如 curl、PDO)默认仍是阻塞的,需搭配支持协程的封装层(如 swoole_http_client、amphp/mysql)
一个最小可行异步示例(需 Swoole 支持)
以下代码利用 Swoole 的协程 MySQL 客户端,在 Fiber 环境中发起并发查询:
立即学习“PHP免费学习笔记(深入)”;
// 启动 Swoole 协程环境(自动管理 Fiber)
Swoole\Runtime::enableCoroutine();
$fiber1 = new Fiber(function() {
$mysql = new Swoole\Coroutine\MySQL();
$mysql->connect(['host' => '127.0.0.1', 'user' => 'root']);
$result = $mysql->query('SELECT SLEEP(1);'); // 非阻塞等待
return $result;
});
$fiber2 = new Fiber(function() {
$mysql = new Swoole\Coroutine\MySQL();
$mysql->connect(['host' => '127.0.0.1', 'user' => 'root']);
$result = $mysql->query('SELECT SLEEP(1);');
return $result;
});
// 并发启动两个 Fiber(Swoole 内部自动 resume/suspend 调度)
$result1 = $fiber1->start();
$result2 = $fiber2->start();
// 主线程不阻塞,可做其他事……然后等待结果
// (实际中由 Swoole 事件循环统一调度,无需手动 resume)
注意:这段代码之所以能并发执行,是因为 Swoole 在底层将 MySQL 查询转为异步 socket 操作,并在 I/O 就绪时自动恢复对应 Fiber。你写的 Fiber 代码看起来是同步的,但执行过程是非阻塞的。
不依赖扩展的纯 Fiber 模拟(仅教学用途)
若暂时不用 Swoole/Amp,可用定时器模拟“伪异步”来理解调度逻辑:
$fiber = new Fiber(function(): string {
echo "请求已发出,等待响应...\n";
$data = Fiber::suspend("pending"); // 主动挂起,告诉主循环:“我等结果”
return "收到: $data";
});
$result = $fiber->start(); // 输出 pending,Fiber 暂停
// 主循环模拟“等待1秒后响应”
usleep(1_000_000);
echo "后台响应就绪\n";
$fiber->resume("Hello from async world!"); // 恢复,传入数据
// 输出:收到: Hello from async world!
这说明 Fiber 提供了「暂停-恢复」的能力,但真正的异步价值,取决于谁在背后监听事件、何时调用 resume。



















