关于协程并发的问题? Barrier::wait($barrier)没能正常工作?

bobshipwood

问题描述

如下图,能正常的到$aa数组,

            $barrier = Barrier::create();
            $aa = [];
            for ($i=1; $i<5; $i++) {
                Coroutine::create(function () use ($barrier, $i, &$aa) {
                    sleep(1);
                    $aa[] = $i;
                });
            }
            // Wait all coroutine done
            Barrier::wait($barrier);
            echo 'all finished';
            var_dump($aa);

        };

照葫芦画瓢,但到了这里就不行了?

$barrier = Barrier::create();
$plcs = [];
foreach ($devicePlcs as $devicePlc) {
    Coroutine::create(function () use ($devicePlc, &$plcs) {
        $plcs[] = $this->test($devicePlc); // 执行实际业务代码;
    });
}
Barrier::wait($barrier);
var_dump($plcs);

 public function test($test)
 {
     static $n = 0;
     sleep(5);
     $n++;
     return $n;
 }

为此你搜索到了哪些方案及不适用的原因

找不到

312 1 1
1个回答

Tinywan

代码是没问题的。协程里使用Timer::sleep(5) 而不是 sleep(5)

  • bobshipwood 2025-10-24

    我解决了,Barrier一定要use 引入,引入就正常了

  • bobshipwood 2025-10-24

    我开头觉得,这个Barrier无需引入啊,也没看到具体在函数内使用的地方,

  • Tinywan 2025-10-24

    来看看执行流程

    1. 协程默认是关闭的,需要单独设置eventLoop开启
    2. 当使用Swoole Swow Fiber驱动时,workerman每次运行onWorkerStart``onMessage onConnect onClose等回调时会自动创建一个协程来执行
    3. 在主协程先使用 Barrier::create() 创建了一个新的协程屏障
    4. 在子协程用使用 use 语法传递屏障,增加引用计数
    5. 在子协程退出时会减少 $barrier 对象的引用计数,直到为 0

    注意:上面的步骤是少了第 4 步:在子协程用使用 use 语法传递屏障,增加引用计数

  • bobshipwood 2025-10-24

    你在哪里看到有这段话的?

  • Tinywan 2025-10-24

    协程屏障 Barrier 是基于PHP引用计数实现的。 https://www.workerman.net/doc/workerman/coroutine/barrier.html

  • bobshipwood 2025-10-24

    奇怪,同样的链接,打开后,没有发现第4步?

  • Tinywan 2025-10-24

    这是我给你分析总结的,官方文档没那么详细

🔝