我想问下,他是怎么实现主副协程切换的,?

bobshipwood

问题描述

官网的例子中,onmessage应该是个主协程的概念吧?然后在开启两个子协程。我想问下流程:

1 在子协程遇到sleep的时候,就直接运行到主协程那,主协程在遇到$result[] = $channel->pop();就阻塞,
2 等待子协程push的时候,主协程就接着运行$result[] = $channel->pop();,然后再次循环,再次遇到阻塞,
3 直到第2个子协程运行完毕,主协程才完毕。

我想问下我的理解正确吗?
如果是正确的,我还想问下,为啥他的底层原理是什么?

 $worker = new Worker('http://0.0.0.0:8001');
 $worker->eventLoop = Swoole::class; // Or Swow::class or Fiber::class
 $worker->onMessage = function (TcpConnection $connection, Request $request) {
            $channel = new Channel(2);
            Coroutine::create(function () use ($channel) {
                sleep(1);
                $channel->push('Task 1 Done');
            });
            Coroutine::create(function () use ($channel) {
                sleep(3);
                $channel->push('Task 2 Done');
            });
            $result = [];
            for ($i = 0; $i < 2; $i++) {
                echo 'main start' . PHP_EOL;
                $result[] = $channel->pop();
                echo 'main stop' . PHP_EOL;
            }
            $connection->send(json_encode($result)); // Response: ["Task 1 Done","Task 2 Done"]
302 3 0
3个回答

agaegha

Swoole的原理应该是替换了PHP的sleep这类会阻塞的c实现函数,深入了解得去看它的源码,这不是PHP的范畴了

胡桃
$channel = new Channel(2);

Coroutine::create( //协程创建立即执行
sleep(1) //suspend 转到外部协程

//。。。

sleep(3); //suspend 转到外部协程
$result[] = $channel->pop(); //i=0 suspend 转到第一个协程  通道为空,产生消费者队列 发生协程切换

sleep(1);// resume
$channel->push('Task 1 Done'); //立即执行,不发生协程切换
sleep(3);// resume
$channel->push('Task 2 Done'); //立即执行,不发生切换 通道刚好能容纳两条数据,不产生生产者队列

$result[] = $channel->pop();  //resume
//。。。

swoole的协程只有名义上的父子关系,没有实质的父子关系(Golang,Swow的子协程会因为父协程的关闭而强制关闭,Swoole的子协程可以活得比父协程更久,除非手动关闭)

  • 暂无评论
huazai

swoole 底层hook了php的相关函数,你以为执行的是 file_get_contents,实际底层已经拦截了这个函数,包装了下

  • 暂无评论
🔝