• 协程与yield


    协程,又称微线程或纤程,是一个比进程和线程更加轻量级的解决方案,现代编程语言基本上都支持。那么协程究竟有什么特点,它是如何运作的呢?

    进程和线程之间的关系我在这篇文章中做了一下比较分析。线程是程序的运行流,所有指令从头到尾按顺序一一执行,进程则是包含线程的容器。在单核CPU中,永远只有一条线程在运行,当然也只可能有一个进程运行,由操作系统内核负责进程和线程的切换。而协程是属于用户空间的,操作系统对其一无所知,由用户自己去做调度。显然用户自己调度比通过使用一个中断让操作系统调度会快很多,这就是协程快的秘诀了。

    那么,协程究竟是一种什么样的存在呢?上面说到线程是一条指令的执行流,那么这个流的则由函数这些最小执行单元组成,函数则可能是包涵或者调用关系,无论是那种,一个函数只有只能完毕,下一个函数才能被执行,例如有两个函数A和B,A由于某些原因被阻塞,那么B肯定就不能运行。协程的出现就是为了解决这个问题,函数可以随时中断,去调用另外的函数。

    Python和PHP5.5以上版本(包含)中,可以利用生成器中的yield在一定程度上实现协程。例如在一个车流量多的路口,摄像头获取车牌号,并保存到文本文件可以这样做:

    #!/usr/bin/env python
    import random
    def getNum(action):
        action.next()
        while True:
            num=random.randint(1000, 9999) #获取车牌号,这里随机
            stored = action.send(num)
            if stored > 500:
                break
        action.close()
    def storage():
        r=0
        while True:
            f=open("./car.txt","a")
            num = yield r
            print num
            if num:
                f.write(str(num)+"
    ")
                r=r+1
        f.close()
    if __name__ == "__main__":
        S=storage()
        getNum(S)
    <?php
    function getNum($action){
        while(1){
            $num=rand(1000,9999);
            $stored = $action->send($num);
            if($stored > 500){
                break;
            }
        }
    }
    function storage(){
        $r=0;
        while(1){
            $num=(yield $r);
            if($num){
                echo $num."
    ";
                file_put_contents("./car.txt",$num."
    ",FILE_APPEND);
                $r++;
            }
        }
    }
    $S=storage();
    getNum($S);

    yield这个关键字在很多语言中都有应用,在PHP和Python中,如果一个函数中含有yield,则这个函数会成为一个生成器(Generator)。上面的例子中,函数之间相互调用并没有在一个函数结束之后,另一个函数才开始运行,而是相互协作,所以称为”协程”,而非线程的抢占式多任务。需要注意的是Python的yield需要用next来启动,而PHP不需要。

    yield只能在一定程度的实现协程,要更加深入理解和使用协程,可以尝试使用gevent,gevent为Python提供了比较完善的协程支持, 能帮助我们自动切换协程,可以获得极高的并发性能。

  • 相关阅读:
    域hash值破解的总结经验
    centos下安装ngnix+php+mysql服务
    方程式EQGRP_Lost_in_Translation工具之fb.py
    Bypass AV meterpreter免杀技巧
    跟我一起创建栈
    vue-cli3使用yarn run build打包找不到路径
    使用vue-cli3快速适配H5项目
    关于判断是安卓还是ios环境跳转下载页
    跟我一起学习webpack输出动态HTML(三)
    跟我一起学习webpack使用配置文件(二)
  • 原文地址:https://www.cnblogs.com/shangdelu/p/8134667.html
Copyright © 2020-2023  润新知