成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Lua的多任務機制—協程(coroutine)

開發
并發是現實世界的本質特征,而聰明的計算機科學家用來模擬并發的技術手段便是多任務機制。大致上有這么兩種多任務技術,一種是搶占式多任務 (preemptive multitasking),它讓操作系統來決定何時執行哪個任務。

并發是現實世界的本質特征,而聰明的計算機科學家用來模擬并發的技術手段便是多任務機制。大致上有這么兩種多任務技術,一種是搶占式多任務 (preemptive multitasking),它讓操作系統來決定何時執行哪個任務。另外一種就是協作式多任務(cooperative multitasking),它把決定權交給任務,讓它們在自己認為合適的時候自愿放棄執行。這兩種多任務方式各有優缺點,前者固有的同步問題使得程序經 常有不可預知的行為,而后者則要求任務具備相當的自律精神。

協程(coroutine)技術是一種程序控制機制,早在上世紀60年代就已提出,用它可以很方便地實現協作式多任務。在主流的程序語言(如 C++、Java、Pascal等)里我們很少能看到協程的身影,但是現在不少動態腳本語言(Python、Perl)卻都提供了協程或與之相似的機制, 其中最突出的便是Lua。

Lua語言實現的協程是一種非對稱式(asymmetric)協程,或稱半對稱式(semi-symmetric)協程,又或干脆就叫半協程 (semi-coroutine)。這種協程機制之所以被稱為非對稱的,是因為它提供了兩種傳遞程序控制權的操作:一種是(重)調用協程(通過 coroutine.resume);另一種是掛起協程并將程序控制權返回給協程的調用者(通過coroutine.yield)。一個非對稱協程可以看 做是從屬于它的調用者的,二者的關系非常類似于例程(routine)與其調用者之間的關系。既然有非對稱式協程,當然也就有對稱式 (symmetric)協程了,它的特點是只有一種傳遞程序控制權的操作,即將控制權直接傳遞給指定的協程。曾經有這么一種說法,對稱式和非對稱式協程機 制的能力并不等價,但事實上很容易根據前者來實現后者。接下來我們就用代碼來證明這個事實。

  1. --對稱式協程庫coro.lua 
  2. --代碼摘自論文"Coroutines in Lua" 
  3. --www.inf.puc-rio.br/~roberto/docs/corosblp.pdf 
  4. coro = {} 
  5. --coro.main用來標識程序的主函數 
  6. coro.main = function() end 
  7. -- coro.current變量用來標識擁有控制權的協程, 
  8. -- 也即正在運行的當前協程 
  9. corocoro.current = coro.main 
  10. -- 創建一個新的協程 
  11. function coro.create(f) 
  12. return coroutine.wrap(function(val) 
  13. return nil,f(val) 
  14. end) 
  15. end 
  16. -- 把控制權及指定的數據val傳給協程k 
  17. function coro.transfer(k,val) 
  18. if coro.current ~= coro.main then 
  19. return coroutine.yield(k,val) 
  20. else 
  21. -- 控制權分派循環 
  22. while k do 
  23. coro.current = k 
  24. if k == coro.main then 
  25. return val 
  26. end 
  27. k,val = k(val) 
  28. end 
  29. error("coroutine ended without transfering control...") 
  30. end 
  31. end 

如果暫時還弄不懂上面的程序,沒關系,看看如何使用這個庫后再回頭分析。下面是使用示例:

  1. require("coro.lua") 
  2. function foo1(n) 
  3. print("1: foo1 received value "..n) 
  4. n = coro.transfer(foo2,n + 10) 
  5. print("2: foo1 received value "..n) 
  6. n = coro.transfer(coro.main,n + 10) 
  7. print("3: foo1 received value "..n) 
  8. coro.transfer(coro.main,n + 10) 
  9. end 
  10. function foo2(n) 
  11. print("1: foo2 received value "..n) 
  12. n = coro.transfer(coro.main,n + 10) 
  13. print("2: foo2 received value "..n) 
  14. coro.transfer(foo1,n + 10) 
  15. end 
  16. function main() 
  17. foo1 = coro.create(foo1) 
  18. foo2 = coro.create(foo2) 
  19. local n = coro.transfer(foo1,0) 
  20. print("1: main received value "..n) 
  21. n = coro.transfer(foo2,n + 10) 
  22. print("2: main received value "..n) 
  23. n = coro.transfer(foo1,n + 10) 
  24. print("3: main received value "..n) 
  25. end 
  26. --把main設為主函數(協程) 
  27. coro.main = main 
  28. --將coro.main設為當前協程 
  29. corocoro.current = coro.main 
  30. --開始執行主函數(協程) 
  31. coro.main() 

上面的示例定義了一個名為main的主函數,整個程序由它而始,也因它而終。為什么需要一個這樣的主函數呢?上面說了,程序控制權可以在對稱式協程 之間自由地直接傳遞,它們之間無所謂誰從屬于誰的問題,都處于同一個層級,但是應用程序必須有一個開始點,所以我們定義一個主函數,讓它點燃程序運行的導 火線。雖說各個協程都是平等的,但做為程序運行原動力的主函數仍然享有特殊的地位(這個世上哪有絕對的平等!),為此我們的庫專門用了一個 coro.main變量來保存主函數,并且在它執行之前要將它設為當前協程(雖然上面的main實際只是一個普通函數而非一個真正的協程,但這并無太大的 關系,以后主函數也被稱為主協程)。示例運行的結果是:

1: foo1 received value 0

1: foo2 received value 10

1: main received value 20

2: foo2 received value 30

2: foo1 received value 40

2: main received value 50

3: foo1 received value 60

3: main received value 70

協程的執行序列是:main->foo1->foo2->main->foo2->foo1->main->foo1->main。

coro.transfer(k,val)函數中k是將要接收程序控制權的協程,而val是傳遞給k的數據。如果當前協程不是主協 程,tansfer(k,val)就簡單地利用coroutine.yield(k,val)將當前協程掛起并傳回兩項數據,即程序控制權的下一站和傳遞 給它的數據;否則進入一個控制權分派(dispatch)循環,該循環(重)啟動(resume)k協程,等待它執行到掛起(suspend),并根據此 時協程傳回的數據來決定下一個要(重)啟動的協程。從應用示例來看,協程與協程之間似乎是用transfer直接傳遞控制權的,但實際上這個傳遞還是通過 了主協程。每一個在主協程里被調用(比較coro.current和coro.main是否相同即可判斷出)的transfer都相當于一個協程管理器, 它不斷地(重)啟動一個協程,將控制權交出去,然后等那個協程掛起時又將控制權收回,然后再(重)啟動下一個協程...,這個動作不會停止,除 非<1>將(重)啟動的協程是主協程;<2>某個協程沒有提供控制權的下一個目的地。很顯然,每一輪分派循環開始時都由主協程把 握控制權,在循環過程中如果控制權的下一站又是主協程的話就意味著這個當初把控制權交出去的主協程transfer操作應該結束了,所以函數直接返回 val從而結束這輪循環。對于情況<2>,因為coro.create(f)創建的協程的體函數(body function)實際是function(val) return nil,f(val) end,所以當函數f的最后一條指令不是transfer時,這個協程終將執行完畢并把nil和函數f的返回值一起返回。如果k是這樣的協 程,transfer執行完k,val = k(val)語句后k值就成了nil,這被視為一個錯誤,因為程序此時沒法確定下一個應該(重)啟動的協程到底是誰。所以在對稱式模型下,每一個協程(當 然主協程除外)最后都必須顯式地將控制權傳遞給其它的協程。根據以上分析,應用示例的控制權的分派應為:

第一輪分派: main->foo1->main->foo2->main->main(結束)

第二輪分派: main->foo2->main->foo1->main->main(結束)

第三輪分派: main->foo1->main->main(結束)

由于可以直接指定控制權傳遞的目標,對稱式協程機制擁有極大的自由,但得到這種自由的代價卻是犧牲程序結構。如果程序稍微復雜一點,那么即使是 非常有經驗的程序員也很難對程序流程有全面而清晰的把握。這非常類似goto語句,它能讓程序跳轉到任何想去的地方,但人們卻很難理解充斥著goto的程 序。非對稱式協程具有良好的層次化結構關系,(重)啟動這些協程與調用一個函數非常類似:被(重)啟動的協程得到控制權開始執行,然后掛起(或結束)并將 控制權返回給協程調用者,這與計算機先哲們倡導的結構化編程風格完全一致。

綜上所述,Lua提供的非對稱式協程不但具有與對稱式協程一樣強大的能力,而且還能避免程序員濫用機制寫出結構混亂的程序。

原文鏈接:http://tech.it168.com/j/2008-02-14/200802141556818.shtml

責任編輯:陳四芳 來源: it168.com
相關推薦

2022-09-06 20:30:48

協程Context主線程

2022-09-12 06:35:00

C++協程協程狀態

2022-09-10 18:51:09

C++協程主線程

2025-06-03 00:00:02

Go協程鎖機制

2014-02-11 09:28:57

2021-09-16 09:59:13

PythonJavaScript代碼

2023-11-17 11:36:59

協程纖程操作系統

2014-06-18 10:41:31

Android多任務機制

2011-08-02 14:48:04

IOS 多任務

2024-02-05 09:06:25

Python協程Asyncio庫

2025-02-08 09:13:40

2025-06-26 04:10:00

2024-06-27 07:56:49

2022-06-08 06:38:00

iPadOS 16SafariiCloud

2012-07-31 09:44:27

Windows Pho

2017-08-10 15:50:44

PHP協程阻塞

2023-10-24 19:37:34

協程Java

2010-02-26 17:47:07

2021-12-09 06:41:56

Python協程多并發

2017-09-22 16:08:16

Python協程編程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲福利在线视频 | 蜜桃臀av一区二区三区 | 中文字幕亚洲欧美日韩在线不卡 | 国产91丝袜在线播放 | 欧产日产国产精品99 | 91亚洲精品久久久电影 | 日韩中文字幕在线免费 | 精品欧美一区二区三区久久久 | 免费在线视频a | 日韩精品一区二区三区中文在线 | 欧美成人精品欧美一级 | 国产视频在线一区二区 | 久久一级 | 91精品国产91久久综合桃花 | 久视频在线观看 | 亚洲欧美在线一区 | 久久另类视频 | 亚洲国产一区二区三区在线观看 | 久久久国产一区二区三区 | 中文字幕一区在线观看视频 | 99久久亚洲 | 国产小视频在线观看 | 在线观看www| 精品国产一区二区三区性色av | 日韩小视频在线 | 久久伊人精品一区二区三区 | 高清一区二区三区 | 亚洲综合区 | 国产在线观看一区二区 | 欧美成人影院 | 亚洲成人精品 | 日韩欧美视频 | 亚洲精品久久久一区二区三区 | 国产中文 | 国产午夜一级 | 亚洲国产激情 | 国产精品美女久久久久久免费 | 日韩午夜在线播放 | 亚洲欧美日韩精品 | 亚洲啊v在线| 黄色免费网站在线看 |