协程容器外代码同步阻塞执行,无调度器;容器内(co\run、启用协程的server/process)才支持go、co::sleep等api,且协程间变量不自动隔离,需用channel通信。

协程容器外的代码永远是同步阻塞执行的,容器内才能用 go、co::sleep 等协程 API;不进容器,协程就根本跑不起来。
协程容器外:没有调度器,只有普通 PHP 执行流
所有在 Co\run() 外、Swoole\Http\Server 启动前、或未启用 swoole.enable_coroutine=1 的代码,都运行在传统 PHP-FPM 模式下:
-
sleep(1)会真正卡住整个进程 1 秒,期间无法响应任何请求 -
curl_exec()、mysqli_query()等 IO 操作全程阻塞,不能被自动协程化 -
go()函数调用会直接报错Warning: go(): coroutine is not available - 即使你写了
co::getCid(),也会返回0(表示当前不在协程中)
协程容器内:协程调度器接管执行权
只有进入容器后,Swoole 才会启动协程调度器,此时 IO 调用才可挂起/恢复。常见入口有三种:
-
Co\run(function () { ... })—— 最直接的裸写方式,适合 CLI 脚本或单元测试 -
Swoole\Http\Server启动时设置enable_coroutine => true,每个请求回调自动进入协程上下文 -
Swoole\Process或Swoole\Process\Pool构造时传['enable_coroutine' => true],子进程自带协程环境
注意:Co\run() 是一次性容器,执行完就退出;而 Server 或 Process 是长期运行的容器,协程可反复创建销毁。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
父子协程优先级与执行顺序容易被误解
很多人以为 go() 是“并发执行”,其实它默认是“深度优先”调度:子协程先跑,直到首次 yield(比如 co::sleep(0.1)),才切回父协程。看这个典型陷阱:
Co\run(function () {
echo "parent start\n";
go(function () {
echo "child 1 start\n";
co::sleep(0.2);
echo "child 1 end\n";
});
go(function () {
echo "child 2 start\n";
co::sleep(0.1);
echo "child 2 end\n";
});
echo "parent end\n";
});
输出顺序是:parent start → child 1 start → child 2 start → parent end → child 2 end → child 1 end。不是并行时间线,而是调度器按创建顺序+yield时机决定谁先 resume。
全局变量和静态属性在容器内外表现完全不同
容器外的 static $x = 0 或 global $y 是进程级共享的;但容器内每个协程都有独立栈,这些变量不会自动隔离:
- 多个协程同时修改同一个
static变量,结果不可预测(无锁竞争) -
go(function () use ($data) { ... })是安全传参方式,$data是值拷贝 - 想跨协程通信,必须用
Swoole\Coroutine\Channel,不能靠全局变量
最常被忽略的一点:协程容器不是“魔法沙盒”,它不自动隔离内存上下文——开发者仍需主动管理数据边界,否则高并发下状态污染比 FPM 更隐蔽、更难复现。










