• 协程


    07.08自我总结

    一.协程的概念

    协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

    需要强调的是:

    #1. python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
    #2. 单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)
    

    对比操作系统控制线程的切换,用户在单线程内控制协程的切换

    优点如下:

    #1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
    #2. 单线程内就可以实现并发的效果,最大限度地利用cpu
    

    缺点如下:

    #1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程来尽可能提高效率
    #2. 协程本质是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
    

    二.协程的应用

    1.greenlet模块

    • 创建协程

    g = greenlet.greenlet(方法)

    只定义不执行

    • 如果需要传参传参

    在执行中进行传参

    g = switch(参数) 且switch这个函数是个阻塞函数,如果上述进程没有进行完毕不会往下运行下去,switch还会命令该协程执行

    如果再方法中有switch如下

    from greenlet import greenlet
    def test1():
        print (12)
        gr2.switch () #切换到g2且保留gr1的运行状态
        print (34)
    
    def test2():
        print (56)
        gr1.switch() #切换到gr1的协程且不是从头开始,而是从gr1保存的运行状态那里接着执行
        print (78)
    
    gr1 = greenlet(test1)
    gr2 = greenlet(test2)
    gr1.switch()
    '''
    12
    56
    34
    '''
    

    2.gevent模块

    • 创建协程

      #创建一个协程
      gevent.joinall([gevent.spawn(func,1,2),gevent.spawn(func,1,2)])
      
      #创建两个协程
      gevent.joinall([gevent.spawn(func,1,2)])
      
      这里创建后他会自动运行,且如果没有什么其他设置,他会安装列表从左往右顺序执行
      
    • monkey

      monkey补丁的原理是把原始的阻塞方法替换为修改后的非阻塞方法,即偷梁换柱,来实现IO自动切换

      原理

      #myjson.py
      def dump():
          print("一个被替换的 dump函数")
      
      def load():
          print("一个被替换的 load函数")
          
      # test.py
      import myjson
      import json
      # 补丁函数
      def monkey_pacth_json():
          json.dump = myjson.dump
          json.load = myjson.load
          
      # 打补丁
      monkey_pacth_json()
      
      # 测试 
      json.dump()
      json.load()
      # 输出:
      # 一个被替换的 dump函数
      # 一个被替换的 load函数
      

    使用

    from gevent import monkey
    monkey.patch_all()
    #patch_all里面的参数
    def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=True, ssl=True,
                  httplib=False, # Deprecated, to be removed.
                  subprocess=True, sys=False, aggressive=True, Event=True,
                  builtins=True, signal=True,
                  queue=True,
                  **kwargs):
        
      默认不处理是全部都打开,只要他们发生io操作就进行其他协程切换
    
  • 相关阅读:
    hashCode花式卖萌
    2017年的小总结
    多线程环境下的单例模式
    Servlet过滤器简单探索
    最长回文子序列(LPS)
    最短编辑距离问题
    赫夫曼编码
    DNA序列对齐问题
    同时寻找序列的最大最小值
    最长公共子序列(LCS)
  • 原文地址:https://www.cnblogs.com/pythonywy/p/11153515.html
一二三 - 开发者的网上家园