• 协程模块gevent


    更新:导入一个有monkey.patch_all()的库,应该用函数把它包起来,不然会抛出错误

    - RuntimeError: cannot release un-acquired lock 

    在《python高性能编程》一书中作者开始讲协程用的就是gevent模块作为例子。先举一个简单的例子:

    协程极大大提高了性能

    如果有100个foo,bar函数,每个需要阻塞一秒,那么串行执行需要100秒以上,而I/O多路复用执行,在一秒之后100个程序执行完毕。

    协程提高性能的原因

      - 所有的阻塞请求同时发生,只要函数输入到位
        -  cpu和操作系统的高度配合

        -可以这么想象   

         1  线程读代码,读到一步需要去取数据,
         2  线程自己不取数据,叫操作系统去取,取数据步骤参考途中1,3,4,2
         3  操作系统取数据,线程就不读代码了,不干其他事,就在这等着
         4 等数据到了,线程继续读代码,按代码干事

     -重点来了,IO多路复用之后事情发生了变化:

       - 线程很快找到查看了代码,发现代码中指出了有一些代码是可以同时执行的
       - 比如下图有4处可以同时执行的代码,

        -每一处代码里面可能也有阻塞,由于更里面的阻塞还不能发起请求主要先不关注,

        - 线程拿起1处的代码,向系统发起请求,不等待,回到代码2处

        - 再去操作系统处发送请求,如此反复,直到代码表明的特殊代码块都发起了请求
       - 线程毫无停歇,只要操作系统使其得到数据,他就运行代码,并重复以上步骤 
       - 对比:在串行的情况下,线程在1.1处停下等待0.1s,而IO多路复用已经把活全做完了


    协程作用的范围:
     -   以下两个条件同时具备

             I/O密集型任务。
                   任务本身结果不受其他任务
     

    如何标记特殊代码块。(猴子补丁+gevent.spawn())

      - 打上猴子补丁

        from gevent import monkey
        monkey.patch_all()

      - gevent.spawn(function,*arg,**kwargs) 

        如果一个function内部没有阻塞,那么到这一步,正常执行
        如果function能有阻塞,那么它被冻结并被标记成特殊代码块
      - 使用内置方法使其开始执行

        gevent.joinall()生成对象是list类型

             iwait生成对象是生成器类型

        对单个对象使用.join()方法,但是无法通过.value获取函数返回值

        对单个对象使用.get()方法,可以直接运行并获得返回值,get(timeout=3)还能设置超时时间
            - 不管哪个方法,生成对象的元素使用.value,得到那些特殊代码块的返回值,

        如果没有返回值,那就不用管

    信号量(from gevent.lock import BoundedSemaphore)

       -  生成计算器对象,并设置值

        bigest=BoundedSemaphore(5)

          生成最大数为5的计数器

       - 在代码中调用

        使用with方法

        或使用bigest.acquire(), bigest.release()

    只能用一次的超时控制(gevent.Timeout):

      - 在.join()方法前加上
         timeout=Timeout(2)

         timeout.start() 

      - timeout支持with调用,其__enter__()方法调用了start(),不知道在函数内部调用会有什么效果?

    还有许多内容,但用好上面这些已能让你代码执行速度快上十倍了。

    好吧,再来一点干货:不同线程内相互控制以及传递值

       import gevent from gevent.event import AsyncResult

      a = AsyncResult()

      a.set('值')
      a.get()='值'

      解释:a实例化时给所有a.get() 后面的代码加锁,然后a.set()解锁,a.get()获取一个值 

      

  • 相关阅读:
    error: with modifiers "public "
    移除元素
    删除有序数组中的重复项
    最长公共前缀
    如何杀死window进程
    IDEA卡顿问题
    合并两个有序链表
    开闭原则
    字符集和sql语句GROUPBY查询的版本问题
    里氏替换原则
  • 原文地址:https://www.cnblogs.com/yuanji2018/p/10016758.html
Copyright © 2020-2023  润新知