面試高頻問題之協程

2021-10-04 17:58:28 字數 2645 閱讀 3472

首先複習一下什麼是程序和執行緒:

程序就是應用程式的啟動例項。比如我們執行乙個遊戲,開啟乙個軟體,就是開啟了乙個程序。

執行緒從屬於程序,是程式的實際執行者。乙個程序至少包含乙個主線程,也可以有更多的子執行緒。

執行緒是程序的一部分,乙個執行緒只能屬於乙個程序,而乙個程序可以有多個執行緒,至少包含乙個主線程。

執行緒和程序的關係如下圖所示:

* 來自網路

協程,英文coroutines,是一種比執行緒更加輕量級的存在。正如乙個程序可以擁有多個執行緒一樣,乙個執行緒也可以擁有多個協程。

協程不是被作業系統核心所管理的,而是完全由程式所控制,也就是在使用者態執行。這樣帶來的好處是效能大幅度的提公升因為不會像執行緒切換那樣消耗資源

協程不是程序也不是執行緒,而是乙個特殊的函式,這個函式可以在某個地方掛起,並且可以重新在掛起處外繼續執行。

乙個程序可以包含多個執行緒,乙個執行緒也可以包含多個協程。簡單來說,乙個執行緒內可以由多個這樣的特殊函式在執行,但是有一點必須明確的是,乙個執行緒的多個協程的執行是序列的。如果是多核cpu,多個程序或乙個程序內的多個執行緒是可以並行執行的,但是乙個執行緒內協程卻絕對是序列的,無論cpu有多少個核。畢竟協程雖然是乙個特殊的函式,但仍然是乙個函式。乙個執行緒內可以執行多個函式,但這些函式都是序列執行的。當乙個協程執行時,其它協程必須掛起。

*下面的內容來自[3]

python對協程的支援還非常有限,用在generator中的yield可以一定程度上實現協程。雖然支援不完全,但已經可以發揮相當大的威力了。

傳統的生產者-消費者模型是乙個執行緒寫訊息,乙個執行緒取訊息,通過鎖機制控制佇列和等待,但一不小心就可能死鎖。如果改用協程,生產者生產訊息後,直接通過yield跳轉到消費者開始執行,待消費者執行完畢後,切換回生產者繼續生產,效率極高:

import time

def consumer():

r = ''

while true:

n = yield r

if not n:

return

print('[consumer] consuming %s...' % n)

time.sleep(1)

r = '200 ok'

def produce(c):

c.next()

n = 0

while n < 5:

n = n + 1

print('[producer] producing %s...' % n)

r = c.send(n)

print('[producer] consumer return: %s' % r)

c.close()

if __name__=='__main__':

c = consumer()

produce(c)

上面的**執行結果為:

[producer] producing 1...

[consumer] consuming 1...

[producer] consumer return: 200 ok

[producer] producing 2...

[consumer] consuming 2...

[producer] consumer return: 200 ok

[producer] producing 3...

[consumer] consuming 3...

[producer] consumer return: 200 ok

[producer] producing 4...

[consumer] consuming 4...

[producer] consumer return: 200 ok

[producer] producing 5...

[consumer] consuming 5...

[producer] consumer return: 200 ok

注意到consumer函式是乙個generator(生成器),把乙個consumer傳入produce後:

首先呼叫c.next()啟動生成器;

然後,一旦生產了東西,通過c.send(n)切換到consumer執行;

consumer通過yield拿到訊息,處理,又通過yield把結果傳回;

produce拿到consumer處理的結果,繼續生產下一條訊息;

produce決定不生產了,通過c.close()關閉consumer,整個過程結束。

整個流程無鎖,由乙個執行緒執行,produce和consumer協作完成任務,所以稱為「協程」,而非執行緒的搶占式多工。

references:

1. 2. 

3. 4. 

C 面試知識 協程

跟程序和執行緒放在一起,只不過相比其他兩個更少的關注度。一種使用者態的輕量級執行緒,完全由使用者排程控制,擁有自己的暫存器上下文和棧,協程排程切換的時候,先將暫存器上下文和棧儲存到其他地方,切換回來的時候再恢復之前儲存的暫存器上下文和棧。直接操作棧則基本沒有核心切換的開銷,可以不加鎖的訪問全域性變數...

面試高頻問題

一般包括專案經驗 其中可以有針對的問一些問題探聽所述的虛實 掌握技術的深度廣度 資料結構 演算法 程式設計能力,專業知識 作業系統,網路,資料庫等 在面試過程中,對候選人的表達能力,思維能力,學習能力,主動性和責任心,對技術是否有熱情等方面做出判斷。探聽虛實,可以問現有專案怎麼做的,也可以現場進行設...

Unity 之 協程 初級

協程可以通過startcoroutine 來呼叫 只需要在裡面穿進去乙個ienumerator型別的方法 就可以了。這個方法是可以帶有引數的哦。舉個例子 ienumerator test2 void start 這樣就在一開始呼叫這個test2的方法了 現在我來著重講講最讓人煩心的yield ret...