• 协程


    协程Coroutine

    协程的目的

    ​ **要在单线程下实现并发,在应用程序里控制多个任务 切换 + 保存(本质) **

    并发: 指的是多个任务同时发生,看似好像是同时进行,其实是切换进行
    并行: 指的是多个任务真正的同时进行

    并发 = 切换 + 保存

    优点:
    应用程序(自己操作)级别的切换速度要快于操作系统的切换速度

    缺点:
    多个任务一旦有一个阻塞没有切,整个线程都阻塞,该线程内的其他的任务都不能执行.

    一旦引入协程,就需要检测单线程下的所有IO,实现遇到IO就切换
    因为有一个任务阻塞了,整个线程都阻塞了,即便是纯计算也要阻塞.

    总结协程特点:

    • 必须在只有一个单线程里实现并发
    • 修改共享数据不需要加锁
    • 用户程序里自己保存多个控制流的上下文栈
    • 一个协程遇到IO操作自动切换到其它协程(如何实现检测IO? yield,greenlet都无法实现, 就用到了gevent模块)

    进程的流程:

    线程的流程:

    协程的流程:

    Greenlet

    """
        使用greenlet模块可以简单完成多个任务之间的切换(使用yield生成器的方式过于麻烦)
    """
    # greenlet(run=None, parent=None): 创建一个greenlet实例
    # g.parent: 每个协程都有一个父协程,当前协程结束后会回到父协程中执行,该属性默认是创建该协程的协程
    # g.run : 该属性是协程实际运行的代码,run方法结束了,那么该协程也结束了
    # g.switch(*args, **kwargs): 切换到g 协程
    # g.throw() :切换到g协程, 接着抛出一个异常
    
    from greenlet import greenlet
    
    
    def eat(name):
        print('%s est 1' % name)
        g2.switch('kp')
        print('%s eat 2' % name)
        g2.switch()
    
    
    def play(name):
        print('%s play 1' % name)
        g1.switch()
        print('%s play 2' % name)
        
    
    g1 = greenlet(eat)
    g2 = greenlet(play)
    
    g1.switch('kopa')
    # kopa est 1
    # kp play 1
    # kopa eat 2
    # kp play 2
    
    
    
    

    Gevent介绍

    Gevent是一种基于协程的Python网络库, 用到Greenlet提供的,封装了libevent事件循环的高层同步API. 用同步的方式写异步IO的代码.

    使用Gevent的新能比一般的线程高, 但是也有坑:

    1, Monkey-patching, 称之为猴子补丁, 因为如果使用了这个补丁,Gevent直接修改标准库里面大部分的阻塞式系统调用, 包括socket,threading和select等模块, 而变成协作式运行. (可能导入补丁会有其他问题)

    2, 第三方库支持

    """
        g1 = gevent.spwan(func,*args, **kwargs) :
            第一个参数是函数名,如eat,后面可以跟参数,参数是传给eat的
    
        g.join() : 等待g 结束
    
        gevent.joinall([g1, g2]) : 等待g1, g2 结束
    
        g.value : 拿到返回值
    
    
    """
    # 猴子补丁放在要补丁的前面(可以看成放在最前面)
    from gevent import monkey
    monkey.patch_all()
    
    import gevent
    import time
    
    def eat():
        print('eat food 1')
        time.sleep(1)
        print('eat food 2')
    
    def play():
        print('play 1')
        time.sleep(1)
        print('play 2')
    
    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(play)
    gevent.joinall([g1, g2])
    print('zhu')
    
    # eat food 1
    # play 1
    # eat food 2
    # play 2
    # zhu
    
  • 相关阅读:
    Web大文件上传断点续传解决方案
    STL 源代码剖析 算法 stl_algo.h -- rotate
    BZOJ 1260 CQOI2007 涂色paint 动态规划
    Shiro学习(总结)
    数组与指针
    Doing Homework again(杭电1789)
    leetCode 75.Sort Colors (颜色排序) 解题思路和方法
    hdu 4786 Fibonacci Tree(最小生成树)
    Havel--Hakimi定理推断可图化 python
    最近小感——一个残疾人写的操作系统
  • 原文地址:https://www.cnblogs.com/kp1995/p/10222482.html
Copyright © 2020-2023  润新知