1. 程序
程序是乙個實體,乙個使用者程式就是乙個程序。
2. 執行緒
3. 子程式
子程式又被稱為執行體、函式、方法等。子程式在主程式中被呼叫執行。
1. 協程的產生
2. 協程的定義
子程式呼叫總是乙個入口,一次返回,呼叫順序是明確的。而協程的呼叫和子程式不同。
比如子程式a、b:
def a()
: print '1'
print '2'
print '3'
def b()
: print 'x'
print 'y'
print 'z'
假設由協程執行,在執行a的過程中,可以隨時中斷,去執行b,b也可能在執行過程中中斷再去執行a,結果可能是:
12x
y3z
但是在a中是沒有呼叫b的,所以協程的呼叫比函式呼叫理解起來要難一些。
看起來a、b的執行有點像多執行緒,但協程的特點在於是乙個執行緒執行,那和多執行緒比,協程有何優勢?
最大的優勢就是協程極高的執行效率。因為子程式切換不是執行緒切換,而是由程式自身控制,因此,沒有執行緒切換的開銷,和多執行緒比,執行緒數量越多,協程的效能優勢就越明顯。
第二大優勢就是不需要多執行緒的鎖機制,因為只有乙個執行緒,也不存在同時寫變數衝突,在協程中控制共享資源不加鎖,只需要判斷狀態就好了,所以執行效率比多執行緒高很多。
因為協程是乙個執行緒執行,那怎麼利用多核cpu呢?最簡單的方法是多程序+協程,既充分利用多核,又充分發揮協程的高效率,可獲得極高的效能。
來看例子:
傳統的生產者-消費者模型是乙個執行緒寫訊息,乙個執行緒取訊息,通過鎖機制控制佇列和等待,但一不小心就可能死鎖。
如果改用協程,生產者生產訊息後,直接通過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 =0while n <5:
n = n +
1print
('[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協作完成任務,所以稱為「協程」,而非執行緒的搶占式多工。
1. 執行緒同步
2. 執行緒非同步
3. 同步與非同步的區別
同步非同步
sockfd 管理單個執行緒管理,方便
多個執行緒共同管理
**邏輯程式整體邏輯清晰
子模組邏輯清晰
程式效能響應時間長,效能差
響應時間短,效能好
總結起來就是:
同步:程式設計簡單,效能差
非同步:程式設計複雜,效能高
同步程式設計簡單是因為其資料的處理是在同乙個過程中進行處理的。但是非同步的處理可能在不同的執行緒中進行處理,例如在非同步的情況下客戶端傳送2次請求,這2個請求可能在服務端的2個執行緒中進行處理,2個執行緒共用乙個客戶端的資料,可能造成資料混亂,最常見的解決方法就是進行加鎖。
總結:
因為協程由使用者程式在使用者棧分配儲存空間,同一執行緒中的多個協程間的切換只在使用者態下,而不涉及核心態,因此這樣的協程不存在使用者態與核心態的轉換,提高了cpu效率。
Lua協程實現原理
api 傳入引數 返回值 說明 api傳入引數 返回值說明 create f 函式,作為協程執行的主函式 返回建立的協程 如果還需要執行,需要使用resume操作 resume co,val1,傳入第乙個引數是create函式返回的協程,剩下的引數是傳遞給協程執行的引數。分兩種情況,resume成功...
協程(四)原理
出處 協程,又稱微執行緒和纖程等,據說源於 simula 和 modula 2 語言 我沒有深究,有錯請指正 現代程式語言基本上都有支援,比如 lua ruby 和最新的 google go,當然也還有最近很讓我驚豔的 falcon。協程是使用者空間執行緒,作業系統其存在一無所知,所以需要使用者自己...
協程(一)原理
賴勇浩 協程,又稱微執行緒和纖程等,據說源於 simula 和 modula 2 語言 我沒有深究,有錯請指正 現代程式語言基本上都有支援,比如 lua ruby 和最新的 google go,當然也還有最近很讓我驚豔的 falcon。協程是使用者空間執行緒,作業系統其存在一無所知,所以需要使用者自...