<?php
use \Swoole\Coroutine;
use \Swoole\Coroutine\WaitGroup;
use \Swoole\Coroutine\Channel;
Coroutine::create(function() {
$wg=new WaitGroup();
$wg->add(1);
// 第一次打印CoroutineList, 会输出主协程ID(=1)
foreach(Coroutine::list() as $key=>$Cid){
var_dump("进程中正在运行的协程ID:".$Cid);
}
Coroutine::create(function() use($wg) {
$Cid=Coroutine::getCid();
var_dump("A.新启动协程ID".$Cid);
Coroutine::sleep(2);
$wg->done();
});
$wg->wait(); // 等待A协程运行结束
foreach(Coroutine::list() as $key=>$Cid){
var_dump("进程中正在运行的协程ID: ".$Cid); // 这里遍历的时候A协程(ID=2)为什么会被遍历出来?
}
$wg->add(1);
Coroutine::create(function() use($wg) {
$Cid=Coroutine::getCid();
var_dump("B.新启动协程ID".$Cid);
Coroutine::sleep(2);
$wg->done();
});
$wg->wait(); // 等待B协程运行结束
foreach(Coroutine::list() as $key=>$Cid){
var_dump("进程中正在运行的协程ID: ".$Cid); // 这里遍历的时候B协程(ID=3)为什么会被遍历出来?
}
});
运行以上代码,结果:
string(34) "进程中正在运行的协程ID:1"
string(20) "A.新启动协程ID2"
string(35) "进程中正在运行的协程ID: 2" // 这里$wg->wait() 等待 A协程(ID=2)结束,才遍历状态,为什么A协程会出现在list列表?
string(35) "进程中正在运行的协程ID: 1"
string(20) "B.新启动协程ID3"
string(35) "进程中正在运行的协程ID: 3" // 这里$wg->wait() 等待 B协程结束,才遍历状态,为什么B协程(ID=3)会出现在list列表?
string(35) "进程中正在运行的协程ID: 1"
@qifengzhang007
$wg->done();会发生一次协程的调度,你可以打印跟踪一下。我这里有一份符合你预期的代码:
<?php
use \Swoole\Coroutine;
use \Swoole\Coroutine\WaitGroup;
use \Swoole\Coroutine\Channel;
use function Co\run;
Coroutine::create(function() {
$wg = new WaitGroup();
$wg->add(1);
// 第一次打印CoroutineList, 会输出主协程ID(=1)
foreach(Coroutine::list() as $key=>$Cid){
var_dump("进程中正在运行的协程ID:".$Cid);
}
Coroutine::create(function() use($wg) {
$Cid=Coroutine::getCid();
var_dump("A.新启动协程ID".$Cid);
Coroutine::sleep(2);
var_dump("1");
$wg->done();
var_dump("2");
});
var_dump("3");
$wg->wait(); // 等待A协程运行结束
var_dump("4");
Coroutine::sleep(0.1);
foreach(Coroutine::list() as $key=>$Cid){
var_dump("进程中正在运行的协程ID: ".$Cid); // 这里遍历的时候A协程(ID=2)为什么会被遍历出来?
}
$wg->add(1);
Coroutine::create(function() use($wg) {
$Cid=Coroutine::getCid();
var_dump("B.新启动协程ID".$Cid);
Coroutine::sleep(2);
$wg->done();
});
$wg->wait(); // 等待B协程运行结束
Coroutine::sleep(0.1);
foreach(Coroutine::list() as $key=>$Cid){
var_dump("进程中正在运行的协程ID: ".$Cid); // 这里遍历的时候B协程(ID=3)为什么会被遍历出来?
}
});
你可以通过getBackTrace来看到B协程仍处于$wg->done那一行, 当你的主协程结束后才会重新返回到B协程并释放它
@huanghantao @twose
非常感谢两位,果然是大神。
尤其是@huanghantao 使用代码示例的方式,通过本人运行对比结果,彻底理解了这个过程。
Most helpful comment
@qifengzhang007
$wg->done();会发生一次协程的调度,你可以打印跟踪一下。我这里有一份符合你预期的代码: