swoole 5 中协程并发控制首选 swoole\coroutine\semaphore,因其是内核级同步原语,能精确限流、避免竞态;需外部创建、acquire/release 成对使用,推荐 try/finally 和带超时的 acquire。

在 Swoole 5 中,协程环境下控制并发数量最直接、可靠的方式就是使用 Swoole\Coroutine\Semaphore(信号量)。它能精确限制同时执行的协程数,避免资源过载或下游服务被压垮。
为什么用 Semaphore 而不是 channel 或 sleep?
Signal-based 控制比手动计数更安全:Semaphore 是内核级协程同步原语,天然支持协程挂起/唤醒,不存在竞态;channel 需自行管理令牌收发,易出错;sleep 纯属“假限流”,无法真正阻塞超额协程。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
基本用法:初始化 + acquire/release
创建一个容量为 N 的信号量,每次并发任务前 acquire(),完成后 release():
$sem = new Swoole\Coroutine\Semaphore(3); // 最多 3 个并发
go(function () use ($sem) {
$sem->acquire(); // 阻塞直到有可用许可
try {
// 执行耗时操作,如 HTTP 请求、数据库查询
co::sleep(1);
echo "done\n";
} finally {
$sem->release(); // 务必释放,建议放 finally
}
});
// 可以并发启动 10 个协程,但只有 3 个真正并行执行
for ($i = 0; $i acquire();
try {
co::httpGet('https://httpbin.org/delay/2');
} finally {
$sem->release();
}
});
}
进阶技巧:带超时的 acquire 避免死等
生产环境建议设置 acquire 超时,防止因上游异常导致协程永久挂起:
-
$sem->acquire(5.0):最多等待 5 秒,超时返回 false - 检查返回值,失败时可降级、记录日志或重试
- 注意:超时后未获得许可,不能调用 release
常见陷阱与注意事项
- 信号量对象必须在协程外创建,不可在 go() 内重复 new —— 每个 new 都是独立实例
- 务必成对调用 acquire/release,推荐用 try/finally 包裹关键逻辑
- 不要在非协程上下文(如主线程、回调函数)中调用 acquire,会报错或阻塞进程
- 若需动态调整并发上限,需重建 Semaphore(Swoole 5 不支持运行时 resize)










