waitgroup需在协程环境中使用,仅含add()、done()、wait()三方法;add()须在go()前调用,done()须用try-finally包裹并成对出现;wait()建议设超时避免死锁。

WaitGroup 不需要配置,只有三个方法可调用:add()、done()、wait();它没有构造参数、不支持超时自动重置、也不能复用。
WaitGroup 必须在协程容器中使用
在 Coroutine
un() 或 Swoole HTTP server 的 onRequest 回调等协程上下文中才能工作。直接在普通 PHP 脚本里 new 一个 WaitGroup 然后 wait(),会立刻报错或死锁。
-
WaitGroup内部依赖协程调度器,wait()是挂起当前协程,不是系统级阻塞 - 如果误在
php test.php这类 CLI 同步脚本里用,wait()会永远卡住——因为根本没有协程环境来唤醒它 - 常见错误现象:
PHP Fatal error: Uncaught SwooleError: wait() must be called in coroutine
add() 和 done() 必须严格成对,且顺序不能颠倒
add() 要在 go() 或 create() 启动协程之前调用;done() 必须在协程退出前执行,否则 wait() 永远不会返回。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 错误写法:在协程内部
$wg->add(),会导致竞态——主协程可能已wait(),但子协程还没来得及add() - 正确写法:
$wg->add(); go(function() use ($wg) { ... $wg->done(); }); - 必须用
try-finally包裹done(),防止异常跳过:try { /* task */ } finally { $wg->done(); } - 若
done()被多调用一次,计数器变负,触发SwooleError: counter can not be negative
wait() 的 timeout 参数容易被忽略但很关键
wait(float $timeout = null) 的 $timeout 是秒级浮点数,设为 0.5 表示最多等 500ms,超时后直接继续执行,不管计数是否归零。
- 不传参或传
null:无限等待,一旦漏掉done()就彻底卡死 - 生产环境强烈建议设超时,比如
$wg->wait(10.0),避免单个异常协程拖垮整个流程 - 超时后
wait()返回false,需手动判断:if (!$wg->wait(5.0)) { echo "timeout"; } - 注意:超时是「从调用
wait()开始」算起,不是从第一个add()算起
真正难的不是写对这三行方法,而是确保每个 go() 都有对应 add(),每个协程路径(包括异常分支)都走到 done()。漏一个,整个 wait 就悬在那里,查起来极难定位。










