day40-并發(fā)編程之協(xié)程

一、協(xié)程

  1. 并發(fā):同一時間段內(nèi),多個任務(wù)執(zhí)行(單核CPU可以實現(xiàn))。
  2. 并行:同一時刻,多個任務(wù)執(zhí)行(只能多核)

協(xié)程是程序員臆想出來的單線程實現(xiàn)并發(fā),在應(yīng)用程序里控制多個任務(wù)的切換+保存狀態(tài)。
yield:生成器,只要函數(shù)中有yield關(guān)鍵字,這個函數(shù)就是生成器,通過yield可以實現(xiàn)保存狀態(tài)+切換

  • 協(xié)程的優(yōu)點:協(xié)程的切換開銷更小,屬于程序級別的切換,操作系統(tǒng)完全感知不到,因而更加輕量級;單線程內(nèi)就可以實現(xiàn)并發(fā)的效果,最大限度地利用cpu。
  • 協(xié)程的缺點:多個任務(wù)一旦有一個阻塞沒有切,整個線程都阻塞在原地
    該線程內(nèi)的其他的任務(wù)都不能執(zhí)行了。

一旦引入?yún)f(xié)程,就需要檢測單線程下所有的IO行為,實現(xiàn)遇到IO就切換,少一個都不行,以為一旦一個任務(wù)阻塞了,整個線程就阻塞了,其他的任務(wù)即便是可以計算,但是也無法運行了。

二、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實現(xiàn)并發(fā)同步或異步編程,在gevent中用到的主要模式是Greenlet, 它是以C擴展模塊形式接入Python的輕量級協(xié)程。 Greenlet全部運行在主程序操作系統(tǒng)進程的內(nèi)部,但它們被協(xié)作式地調(diào)度。

用法

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執(zhí)行完成
    p.join()
    print('主')
    print(time.time() - ctim)  #2.0165154933929443

四、asyncio

# 官方支持協(xié)程的庫



# import time
# import asyncio
#
# # 把普通函數(shù)變成協(xié)程函數(shù)
# # 3.5以前這么寫
# @asyncio.coroutine
# def task():
#     print('開始了')
#     yield from asyncio.sleep(1)  #asyncio.sleep(1)模擬io
#     print('結(jié)束了')
#
#
# loop=asyncio.get_event_loop()  # 獲取一個時間循環(huán)對象#
#
# # 協(xié)程函數(shù)加括號,并不會真正的去執(zhí)行,它需要提交給loop,讓loop循環(huán)著去執(zhí)行
# # 協(xié)程函數(shù)列表
#
# 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
# 表示我是協(xié)程函數(shù),等同于3.5之前的裝飾器
async def task():
    print('開始了')
    print(current_thread().name)
    await asyncio.sleep(3)  # await等同于原來的yield from
    print('結(jié)束了')

async def task2():
    print('開始了')
    print(current_thread().name)
    await asyncio.sleep(2)
    print('結(jié)束了')

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模型

點擊進入……

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容