美文网首页
day40-并发编程之协程

day40-并发编程之协程

作者: 天行_b6d0 | 来源:发表于2020-09-03 19:40 被阅读0次

    一、协程

    1. 并发:同一时间段内,多个任务执行(单核CPU可以实现)。
    2. 并行:同一时刻,多个任务执行(只能多核)

    协程是程序员臆想出来的单线程实现并发,在应用程序里控制多个任务的切换+保存状态。
    yield:生成器,只要函数中有yield关键字,这个函数就是生成器,通过yield可以实现保存状态+切换

    • 协程的优点:协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级;单线程内就可以实现并发的效果,最大限度地利用cpu。
    • 协程的缺点:多个任务一旦有一个阻塞没有切,整个线程都阻塞在原地
      该线程内的其他的任务都不能执行了。

    一旦引入协程,就需要检测单线程下所有的IO行为,实现遇到IO就切换,少一个都不行,以为一旦一个任务阻塞了,整个线程就阻塞了,其他的任务即便是可以计算,但是也无法运行了。

    二、greenlet模块

    greenlet模块遇到IO不会切换

    from greenlet import greenlet
    import time
    # 遇到io不会切,初级模块,gevent模块基于它写的,处理io切换
    def eat():
        print('我吃了一口')
        p.switch()
        print('我又吃了一口')
        p.switch()
    
    
    def play():
        print('我玩了一会')
        e.switch()
        print('我又玩了一会')
    
    
    if __name__ == '__main__':
        e = greenlet(eat)
        p = greenlet(play)
        e.switch()
    

    三、gevent模块

    使用gevent库需要先安装:

    #安装
    pip3 install gevent
    

    Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

    用法

    import gevent
    import time
    
    def eat(name):
        print('%s 吃了一口' % name)
        gevent.sleep(1)
        print('%s 又吃了一口' % name)
    
    
    def play(name):
        print('%s 玩了一会' % name)
        gevent.sleep(2)
        print('%s 又玩了一会' % name)
    
    
    if __name__ == '__main__':
        ctim = time.time()
        e = gevent.spawn(eat,'lqz')
        p = gevent.spawn(play,'lqz')
        e.join() # 等待e执行完成
        p.join()
        print('主')
        print(time.time() - ctim)  #2.0165154933929443
    

    四、asyncio

    # 官方支持协程的库
    
    
    
    # import time
    # import asyncio
    #
    # # 把普通函数变成协程函数
    # # 3.5以前这么写
    # @asyncio.coroutine
    # def task():
    #     print('开始了')
    #     yield from asyncio.sleep(1)  #asyncio.sleep(1)模拟io
    #     print('结束了')
    #
    #
    # loop=asyncio.get_event_loop()  # 获取一个时间循环对象#
    #
    # # 协程函数加括号,并不会真正的去执行,它需要提交给loop,让loop循环着去执行
    # # 协程函数列表
    #
    # ctime=time.time()
    # t=[task(),task()]
    # loop.run_until_complete(asyncio.wait(t))
    # loop.close()
    # print(time.time()-ctime)
    
    
    import time
    import asyncio
    from threading import current_thread
    # 表示我是协程函数,等同于3.5之前的装饰器
    async def task():
        print('开始了')
        print(current_thread().name)
        await asyncio.sleep(3)  # await等同于原来的yield from
        print('结束了')
    
    async def task2():
        print('开始了')
        print(current_thread().name)
        await asyncio.sleep(2)
        print('结束了')
    
    loop=asyncio.get_event_loop()
    
    ctime=time.time()
    t=[task(),task2()]
    loop.run_until_complete(asyncio.wait(t))
    loop.close()
    print(time.time()-ctime)
    

    五、io模型

    点击进入……

    相关文章

      网友评论

          本文标题:day40-并发编程之协程

          本文链接:https://www.haomeiwen.com/subject/tkvcsktx.html