4 1 協程介紹

2021-09-10 22:48:41 字數 3307 閱讀 4564

本節的主題是基於單執行緒來實現併發,即只用乙個主線程(很明顯可利用的cpu只有乙個)情況下實現併發,為此我們需要先回顧下併發的本質:切換+儲存狀態

cpu正在執行乙個任務,會在兩種情況下切走去執行其他的任務(切換由作業系統強制控制),一種情況是該任務發生了阻塞,另外一種情況是該任務計算的時間過長或有乙個優先順序更高的程式替代了它

ps:在介紹程序理論時,提及程序的三種執行狀態,而執行緒才是執行單位,所以也可以將上圖理解為執行緒的三種狀態
一:其中第二種情況並不能提公升效率,只是為了讓cpu能夠雨露均沾,實現看起來所有任務都被「同時」執行的效果,如果多個任務都是純計算的,這種切換反而會降低效率。為此我們可以基於yield來驗證。yield本身就是一種在單執行緒下可以儲存任務執行狀態的方法,我們來簡單複習一下:

1 yiled可以儲存狀態,yield的狀態儲存與作業系統的儲存執行緒狀態很像,但是yield是**級別控制的,更輕量級

2 send可以把乙個函式的結果傳給另外乙個函式,以此實現單執行緒內程式之間的切換

單純地切換反而會降低執行效率

#序列執行

import time

def consumer(res):

'''任務1:接收資料,處理資料'''

pass

def producer():

'''任務2:生產資料'''

res=

for i in range(10000000):

return res

start=time.time()

#序列執行

res=producer()

consumer(res) #寫成consumer(producer())會降低執行效率

stop=time.time()

print(stop-start) #1.5536692142486572

#基於yield併發執行

import time

def consumer():

'''任務1:接收資料,處理資料'''

while true:

x=yield

def producer():

'''任務2:生產資料'''

g=consumer()

next(g)

for i in range(10000000):

g.send(i)

start=time.time()

#基於yield儲存狀態,實現兩個任務直接來回切換,即併發的效果

#ps:如果每個任務中都加上列印,那麼明顯地看到兩個任務的列印是你一次我一次,即併發執行的.

producer()

stop=time.time()

print(stop-start) #2.0272178649902344

二:第一種情況的切換。在任務一遇到io情況下,切到任務二去執行,這樣就可以利用任務一阻塞的時間完成任務二的計算,效率的提公升就在於此。

yield並不能實現遇到io切換

import time

def consumer():

'''任務1:接收資料,處理資料'''

while true:

x=yield

def producer():

'''任務2:生產資料'''

g=consumer()

next(g)

for i in range(10000000):

g.send(i)

time.sleep(2)

start=time.time()

producer() #併發執行,但是任務producer遇到io就會阻塞住,並不會切到該執行緒內的其他任務去執行

stop=time.time()

print(stop-start)

對於單執行緒下,我們不可避免程式**現io操作,但如果我們能在自己的程式中(即使用者程式級別,而非作業系統級別)控制單執行緒下的多個任務能在乙個任務遇到io阻塞時就切換到另外乙個任務去計算,這樣就保證了該執行緒能夠最大限度地處於就緒態,即隨時都可以被cpu執行的狀態,相當於我們在使用者程式級別將自己的io操作最大限度地隱藏起來,從而可以迷惑作業系統,讓其看到:該執行緒好像是一直在計算,io比較少,從而更多的將cpu的執行許可權分配給我們的執行緒。

協程的本質就是在單執行緒下,由使用者自己控制乙個任務遇到io阻塞了就切換另外乙個任務去執行,以此來提公升效率。為了實現它,我們需要找尋一種可以同時滿足以下條件的解決方案:
1. 可以控制多個任務之間的切換,切換之前將任務的狀態儲存下來,以便重新執行時,可以基於暫停的位置繼續執行。

2. 作為1的補充:可以檢測io操作,在遇到io操作的情況下才發生切換

協程:是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明什麼是執行緒:協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的。、需要強調的是:

1. python的執行緒屬於核心級別的,即由作業系統控制排程(如單執行緒遇到io或執行時間過長就會被迫交出cpu執行許可權,切換其他執行緒執行)

2. 單執行緒內開啟協程,一旦遇到io,就會從應用程式級別(而非作業系統)控制切換,以此來提公升效率(!!!非io操作的切換與效率無關)

對比作業系統控制線程的切換,使用者在單執行緒內控制協程的切換

優點如下:

1. 協程的切換開銷更小,屬於程式級別的切換,作業系統完全感知不到,因而更加輕量級

2. 單執行緒內就可以實現併發的效果,最大限度地利用cpu

缺點如下:

1. 協程的本質是單執行緒下,無法利用多核,可以是乙個程式開啟多個程序,每個程序內開啟多個執行緒,每個執行緒內開啟協程

2. 協程指的是單個執行緒,因而一旦協程出現阻塞,將會阻塞整個執行緒

總結協程特點:

必須在只有乙個單執行緒裡實現併發修改共享資料不需加鎖使用者程式裡自己儲存多個控制流的上下文棧附加:乙個協程遇到io操作自動切換到其它協程(如何實現檢測io,yield、greenlet都無法實現,就用到了gevent模組(select機制))

python 併發程式設計 協程 協程介紹

協程 是單執行緒下的併發,又稱微執行緒,纖程。英文名coroutine。一句話說明什麼是執行緒 協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的 需要強調的是 1.python的執行緒屬於核心級別的,即由作業系統控制排程 如單執行緒遇到io或執行時間過長就會被迫交出cpu執行許可...

協程巢狀協程

import asyncio import functools 第三層協程 async def test1 print 我是test1 await asyncio.sleep 1 print test1已經睡了1秒 await asyncio.sleep 3 print test1又睡了3秒 ret...

9 協程 協程理論

本節的主題是基於單執行緒來實現併發,即只用乙個主線程 很明顯可利用的cpu只有乙個 情況下實現併發,為此我們需要先回顧下併發的本質 切換 儲存狀態 ps 在介紹程序理論時,提及程序的三種執行狀態,而執行緒才是執行單位,所以也可以將上圖理解為執行緒的三種狀態cpu正在執行乙個任務,會在兩種情況下切走去...