讀《programming in lua》協程那一章,比較困惑的還是procuer-consumer那個例子:
functionconsumer(prod)
while
true
dolocal x =receive(prod)
(x)
endend
function
receive(prod)
local status, value = coroutine.resume
(prod)
return
value
endfunction
send(x)
coroutine.yield(x) --
go back to where resumed
endfunction
producer()
return
coroutine.create(function
()
while
true
dolocal x = io.read
() send(x)
endend
)end
--consumer-driven design
consumer(producer())
producer產生資料,consumer消費資料,producer與consumer都在各自的協程中完成, **很短,但是很難讀 - 至少不是那麼一目了然,尤其比起這個直接的迴圈:
functionproduce()
return
io.read
()end
function
consume(x)
(x)end
while
true
dolocal x =produce()
consume(x)
end
好在**?
書中說可以新增快取控制速度,或者進行資料過濾 - 但是這在迴圈版本的producer-consumer中也都能做到,無非在在實現produce是多些邏輯,或者再加個filter的函式處理produce的返回值,協程版本毫無優勢可言。
實在要說其優點,恐怕只是:producer和consumer的**在各自的協程中實現,並通過resume-yield交換資料 - 實現了松耦合。這是個優點,可以還是不太滿意,再往下看時,看到了全排列那個例子,稍作修改,讓我比較直觀的感覺到了協程這種控制結構的靈活性:
functionsend(a)
coroutine.yield
(a)end
function
receive(prod)
local status, value = coroutine.resume
(prod)
return
value
endfunction
consumer(prod)
local
function
print_result(a)
for _, v in
ipairs(a) do
io.write(v, "")
endio.write('\n'
)
endwhile
true
dolocal a =receive(prod)
ifnot a then
break
endprint_result(a)
endend
function
producer(a)
function
permgen(a, n)
if n == 0
then
send(a)
--send something for consuming from an recursive call
else
for i=1, n do
a[n], a[i] =a[i], a[n]
permgen(a, n-1
) a[n], a[i] =a[i], a[n]
endend
endlocal n =table.getn(a)
return
coroutine.create(function() permgen(a, n) end
)end
consumer(producer())
這裡全排列採用了遞迴演算法:對陣列中的每個元素,把它交換到陣列末尾,然後對前n-1個元素的子陣列做同樣的事,當n==0時,輸出乙個排列。
這個在produce的時候,因為在乙個遞迴呼叫中,你無法乙個個返回:
於是,協程的有點就顯現出來了,不同於簡單函式中的return,協程可以在找到乙個排列後,yield掛起本協程並返回該排列,返回到原來resume這個協程的**處,取得資料進行consume,然後繼續resume進入協程獲取排列 - 通過協程靈活控制流程並傳遞資料,十分漂亮。
所以,那個迴圈版本的問題是:並不是所有produce的資料,都可以簡單的return回來的。
對協程的理解
對於作業系統來說,協程其實是一種特殊的執行緒,對於cpu來說,協程是非搶占式 程序和執行緒是搶占式的 實現機理如下 有兩個function a,b,a呼叫b,b要執行一段時間,很晚才返回,a不會因為等b而一直占用cpu,即a是非阻塞的。b返回後,a又能繼續執行。神奇的是,a和b又是走在一條獨木橋 橋...
對協程的理解
實現併發,可以使用多程序,多執行緒。程序和執行緒有個共同點,他們都是通過作業系統來排程的。而協程,則把排程的權力交給了程式設計師。協程可以看作使用者態下協作的執行緒。使用者態 是說協程的排程權屬於程式設計師。協作 是說協程的排程是協作式的,不是搶占的。在協程中,某部分可以通過呼叫某個方法,將控制權交...
Lua的協程基礎
參考 lua中的協同程式 coroutine 協同程式 coroutine 三個狀態 suspended 掛起,協同剛建立完成時或者yield之後 running 執行 dead 函式走完後的狀態,這時候不能再重新resume coroutine.create arg 根據乙個函式建立乙個協同程式,...