Lua 學習筆記(九)協同程序(線程thread)


     協同程序與線程thread差不多,也就是一條執行序列,擁有自己獨立的棧、局部變量和命令指針,同時又與其他協同程序共享全局變量和其他大部分東西。從概念上講線程與協同程序的主要區別在於,一個具有多個線程的程序可以同時運行幾個線程,而協同程序卻需要彼此協作的運行。也就是說多個協同程序在任意時刻只能運行一個協同程序,只有當正在運行的協同程序顯式的要求掛起時,它的執行才會暫停。

 
一、協同程序coroutine
 
     Lua將所有關於協同程序的函數放置在一個名為“coroutine”的table中。
     1、coroutine.create創建一個thread類型的值表示新的協同程序,返回一個協同程序。
     2、coroutine.status檢查協同程序的狀態(掛起suspended、運行running、死亡dead、正常normal)。
     3、coroutine.resume啟動或再次啟動一個協同程序,並將其狀態由掛起改為運行。
     4、coroutine.yield讓一個協同程序掛起。
     5、coroutine.wrap同樣創建一個新的協同程序,返回一個函數。
 
     創建協同程序:create函數,接受一個函數值作為協同程序的執行內容,並返回一個協同程序。
 
 
     啟動或再次啟動一個協同程序:resume函數,接受一個協同程序及一個或多個參數用於值傳遞給協同程序。
 
 
     掛起協同程序:yield函數,讓一個協同程序掛起,並等待下次恢復它的運行。它可以接受resume函數傳遞進來的所有參數。
 
 
     關於wrap函數的使用,wrap函數比create函數更易使用。它提供了一個對於協同程序編程實際所需的功能,即一個可以喚醒協同程序的函數。但也缺乏靈活性。無法檢查wrap所創建的協同程序的狀態,此外,也無法檢測出運行時的錯誤。
 
 
     各種協同狀態的演示:
 
 
     首先,Lua提供的是一種:”非對稱的協同程序“。也就是說,Lua提供了兩個函數來控制協同程序的執行,一個用於掛起執行,另一個用於恢復執行。而一些其他的語言則提供了”對稱的協同程序“,其中只有一個函數用於轉讓協同程序之間的執行權。
 
二、管道與過濾器filter
 
     關於協同程序的示例就是”生產者--消費者“的問題。其中涉及到兩個函數,一個函數不斷的產生值,另一個函數不斷的消費這些值。當消費者需要一個新的值時,它喚醒生產者。生產者返回一個新值后停止運行,等待消費者的再次喚醒。這種設計稱為”消費者驅動“。通過resume—yield 函數之間的值交換可以輕易的實現程序。
 
     過濾器filter,是一種位於生產者與消費者之間的處理功能,可以進行數據轉換。它既是消費者又是生產者,它喚醒生產者促使其生產新值,然后又將變換后的值傳遞給消費者。
 
 1 --管道與過濾器filter
 2 --生產者與消費者通過過濾器進行值傳遞
 3 --這種模式通過消費者驅動生產者進行產生。
 4 
 5 --計數器函數
 6 function getCount( x )
 7      return function()
 8           x=x+1
 9           return x
10      end
11 end
12 --創建閉合計數器
13 local count = getCount(0)
14 --發送新值
15 function send(x)
16      coroutine.yield(x)
17 end
18 --啟動一個協同程序
19 function receive( pro )
20      local status,value = coroutine.resume( pro )
21      return value
22 end
23 --生產者
24 function producter()
25      while true do
26           send( count() )
27      end
28 end
29 --過濾器,接受一個生產者
30 function filter( pro )
31      local x = 0
32      return function()
33           while true do
34                x = receive( pro )
35                send(x)
36           end
37      end
38 end
39 --消費者,接受一個生產者協同程序及控制條件,控制條件防止死循環
40 --假設有100個消費者,驅動生產者來生產
41 function consumer( pro,num )
42      local x = 0
43      while x < num do
44           x = receive( pro )
45           print( x )
46      end
47 end
48 
49 local pro = coroutine.create( producter )
50 local fil = coroutine.create( filter( pro ) )
51 consumer( fil,100 )
52 
53 print( "消費者協同程序狀態:",coroutine.status(pro) )
54 print( "生產者協同程序狀態:",coroutine.status(fil) )

 
 
三、協同程序實現的迭代器
 
     通過“生產者—消費者”模型可以很輕松的創建迭代器,同樣是通過協同程序來進行控制。
 
--以協同程序實現Lua迭代器

local tab = { 1,2,3,4,5,6 }

function corFun( tab,num )
     num = num or 0
     return function()
          while true do
               num = num +1
               if( num > #tab ) then return end
               coroutine.yield(tab[num])
          end
     end
end

function cor( tab )
     local cor = coroutine.create( corFun( tab ) )
     return function ()--迭代器
          local status,value = coroutine.resume( cor )
          return value
     end
end

for v in cor( tab ) do
     if v then
          print(v)
     else
          break
     end
end

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM