hyperf 3.1 中必须用 channel 实现协程通信与同步:无缓冲 channel 用于强制协程“握手”同步;有缓冲 channel 可控制并发数,如 capacity=3 实现轻量限流;须避免单协程双向操作、确保收发协程配对、正确关闭 channel 防死锁。

Hyperf 3.1 中协程间需安全传递数据并控制并发执行节奏,不能靠全局变量或锁硬扛,必须用 Channel 实现通信与同步。
创建并使用无缓冲 Channel 进行协程同步
第一步:在控制器方法中调用 new Channel() 创建无缓冲通道,它天然强制发送方和接收方“碰头”才能完成一次通信。
第二步:用 Coroutine::create() 启动两个协程,一个向 channel 发送字符串,另一个从 channel 接收——注意:两个协程必须都启动后,【发送操作才会真正完成,否则会永久阻塞】。
第三步:主协程调用 $channel->pop() 获取数据,这一步会等待直到有协程完成推送。无缓冲 channel 的行为就是“握手即走”,不存数据,不缓存,不排队。
用有缓冲 Channel 控制并发任务数量
方法一:声明时指定容量,例如 $channel = new Channel(3),表示最多暂存 3 条未被消费的消息。
方法二:在循环中启动多个协程执行耗时任务(如 HTTP 请求),每个协程执行前先调用 $channel->push(true) 占位,任务完成后调用 $channel->pop() 释放槽位。
方法三:把 $channel->push(true) 放在协程最开头,就能天然实现“最多同时运行 3 个请求”,超出的协程会在 push 这一步挂起,等前面的协程 pop 后才继续——【这是最轻量的并发数硬限流方式,无需额外计数器或信号量】。
避免 Channel 死锁的三个关键动作
① 永远不要在单个协程里既 send 又 receive 同一个无缓冲 channel——这等于自己等自己,必然卡死。
② 向 channel 发送数据前,确认已有接收协程在等待,或改用 select + default 防阻塞:select { case $channel->push($val): break; default: Log::warning('channel 已满,丢弃数据'); }。
③ 关闭 channel 前,确保所有发送协程已退出,且仅关闭一次;重复 close 会 panic,而对已关闭的 channel 再 push 也会 panic。











