協程(四)原理

2021-07-23 08:01:54 字數 3183 閱讀 3343

出處:

協程,又稱微執行緒和纖程等,據說源於 simula 和 modula-2 語言(我沒有深究,有錯請指正),現代程式語言基本上都有支援,比如 lua、ruby 和最新的 google go,當然也還有最近很讓我驚豔的 falcon。協程是使用者空間執行緒,作業系統其存在一無所知,所以需要使用者自己去做排程,用來執行協作式多工非常合適。其實用協程來做的東西,用執行緒或程序通常也是一樣可以做的,但往往多了許多加鎖和通訊的操作。

下面是生產者消費者模型的基於搶占式多執行緒程式設計實現(偽**):

// 佇列容器

var q := new queue

// 消費者執行緒

loop

lock(q)

get item from q

unlock(q)

if item

use this item

else

sleep 

// 生產者執行緒

loop

create some new items

lock(q)

add the items to q

unlock(q)

由以上**可以看到執行緒實現至少有兩點硬傷:

1、對佇列的操作需要有顯式/隱式(使用執行緒安全的佇列)的加鎖操作。

2、消費者執行緒還要通過 sleep 把 cpu 資源適時地「謙讓」給生產者執行緒使用,其中的適時是多久,基本上只能靜態地使用經驗值,效果往往不由人意。

而使用協程可以比較好的解決這個問題,下面來看一下基於協程的生產者消費者模型實現(偽**):

// 佇列容器

var q := new queue

// 生產者協程

loop

while q is not full

create some new items

add the items to q

yield to consume

// 消費者協程

loop

while q is not empty

remove some items from q

use the items

yield to produce

可以從以上**看到之前的加鎖和謙讓 cpu 的硬傷不復存在,但也損失了利用多核 cpu 的能力。所以選擇執行緒還是協程,就要看應用場合了。下面簡單談一下協程常見的用武之地,其中之一是狀態機,能夠產生更高可讀性的**;還有就是並行的角色模型,這在遊戲開發中比較常見;以及產生器, 有助於對輸入/輸出和資料結構的通用遍歷。

協程雖然如此之好,看是很長時間以來,因為受到基於堆疊的子例程實現的限制,並沒有多少語言在其實語言或庫中支援協程,所以執行緒作為乙個替代者(當然,執行緒也有其超越協程之處)被廣泛接受了。但是在今天,很多語言都內建了協程的支援,甚至是 c/c++ 語言。ms windows 2000 以後的版本,都支援所謂的 fiber,即纖程,其實就是協程的別稱;在開源平台,posix 標準也定義了協程相關的標準,gnu portable threads 實現了跨平台的使用者空間執行緒,即協程的另一種別稱。在這百花齊放的時節,正是我們好好學習和利用它的時機。

接下來我將在第二篇中談談遊戲中試用協程的三個場合。

協程,又稱微執行緒和纖程等,據說源於 simula 和 modula-2 語言(我沒有深究,有錯請指正),現代程式語言基本上都有支援,比如 lua、ruby 和最新的 google go,當然也還有最近很讓我驚豔的 falcon。協程是使用者空間執行緒,作業系統其存在一無所知,所以需要使用者自己去做排程,用來執行協作式多工非常合適。其實用協程來做的東西,用執行緒或程序通常也是一樣可以做的,但往往多了許多加鎖和通訊的操作。

下面是生產者消費者模型的基於搶占式多執行緒程式設計實現(偽**):

// 佇列容器

var q := new queue

// 消費者執行緒

loop

lock(q)

get item from q

unlock(q)

if item

use this item

else

sleep 

// 生產者執行緒

loop

create some new items

lock(q)

add the items to q

unlock(q)

由以上**可以看到執行緒實現至少有兩點硬傷:

1、對佇列的操作需要有顯式/隱式(使用執行緒安全的佇列)的加鎖操作。

2、消費者執行緒還要通過 sleep 把 cpu 資源適時地「謙讓」給生產者執行緒使用,其中的適時是多久,基本上只能靜態地使用經驗值,效果往往不由人意。

而使用協程可以比較好的解決這個問題,下面來看一下基於協程的生產者消費者模型實現(偽**):

// 佇列容器

var q := new queue

// 生產者協程

loop

while q is not full

create some new items

add the items to q

yield to consume

// 消費者協程

loop

while q is not empty

remove some items from q

use the items

yield to produce

可以從以上**看到之前的加鎖和謙讓 cpu 的硬傷不復存在,但也損失了利用多核 cpu 的能力。所以選擇執行緒還是協程,就要看應用場合了。下面簡單談一下協程常見的用武之地,其中之一是狀態機,能夠產生更高可讀性的**;還有就是並行的角色模型,這在遊戲開發中比較常見;以及產生器, 有助於對輸入/輸出和資料結構的通用遍歷。

協程雖然如此之好,看是很長時間以來,因為受到基於堆疊的子例程實現的限制,並沒有多少語言在其實語言或庫中支援協程,所以執行緒作為乙個替代者(當然,執行緒也有其超越協程之處)被廣泛接受了。但是在今天,很多語言都內建了協程的支援,甚至是 c/c++ 語言。ms windows 2000 以後的版本,都支援所謂的 fiber,即纖程,其實就是協程的別稱;在開源平台,posix 標準也定義了協程相關的標準,gnu portable threads 實現了跨平台的使用者空間執行緒,即協程的另一種別稱。在這百花齊放的時節,正是我們好好學習和利用它的時機。

接下來我將在第二篇中談談遊戲中試用協程的三個場合。

沒有啥複雜的東西,考慮清楚需求,就可以很自然的衍生出這些解決方案。

本質上協程就是使用者空間下的執行緒。

協程(一)原理

賴勇浩 協程,又稱微執行緒和纖程等,據說源於 simula 和 modula 2 語言 我沒有深究,有錯請指正 現代程式語言基本上都有支援,比如 lua ruby 和最新的 google go,當然也還有最近很讓我驚豔的 falcon。協程是使用者空間執行緒,作業系統其存在一無所知,所以需要使用者自...

Lua協程實現原理

api 傳入引數 返回值 說明 api傳入引數 返回值說明 create f 函式,作為協程執行的主函式 返回建立的協程 如果還需要執行,需要使用resume操作 resume co,val1,傳入第乙個引數是create函式返回的協程,剩下的引數是傳遞給協程執行的引數。分兩種情況,resume成功...

協程 底層實現原理

1.程序程序是乙個實體,乙個使用者程式就是乙個程序。2.執行緒 3.子程式子程式又被稱為執行體 函式 方法等。子程式在主程式中被呼叫執行。1.協程的產生 2.協程的定義 子程式呼叫總是乙個入口,一次返回,呼叫順序是明確的。而協程的呼叫和子程式不同。比如子程式a b def a print 1 pri...