日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入理解lua的协程coroutine

發布時間:2024/2/28 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解lua的协程coroutine 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 概述

lua協程和多線程

相同之處:擁有自己獨立的桟、局部變量和PC計數器,同時又與其他協程共享全局變量和其他大部分東西

不同之處:一個多線程程序可以同時運行幾個線程(并發執行、搶占),而協程卻需要彼此協作地運行,并非真正的多線程,即一個多協程程序在同一時間只能運行一個協程,并且正在執行的協程只會在其顯式地要求掛起(suspend)時,它的執行才會暫停(無搶占、無并發)。注意:由于Lua中的協程無法在外部將其停止,而且有可能導致程序阻塞

2. 函數介紹

Lua中所有與協程相關的函數都在coroutine(一個table)中,其中主要的函數如下

其他函數:

2.1 coroutine.isyieldable()? ? :????如果正在運行的協程可以讓出,則返回true。值得注意的是,只有主協程(線程)和C函數中是無法讓出的

2.2?coroutine.wrap()????????? ?:????wrap()也是用來創建協程的

只不過這個協程的句柄是隱藏的。跟create()的區別在于:

(1)、wrap()返回的是一個函數,每次調用這個函數相當于調用coroutine.resume()。

(2)、調用這個函數相當于在執行resume()函數。

?

?

(3)、調用這個函數時傳入的參數,就相當于在調用resume時傳入的除協程的句柄外的其他參數。

?

?

(4)、調用這個函數時,跟resume不同的是,它并不是在保護模式下執行的,若執行崩潰會直接向外拋出

? ? wrap()函數的示例代碼:

co = coroutine.wrap(????function (a,b)print("resume args:"..a..","..b)yreturn = coroutine.yield()print ("yreturn :"..yreturn)end) print(type(co)) co(11,22) co(33)

????結果如下:

function resume args:11,22 yreturn :33

特別注意:

1. coroutine.resume()函數

用來首次啟動或再次啟動一個協程,使其由掛起狀態變成運行狀態。也可以這么說,resume函數相當于在執行協程中的方法。參數Val1...是執行協程co時傳遞給協程的參數。
(1)?
首次調用resume執行協程co時,參數Val1...會賦值給協程co的函數,作為函數參數

(2) 以后調用resume執行協程co時,參數Val1...會賦值給協程co中上一次yield的返回值

resume函數的返回有3種情況:

(1)?如果協程co的函數執行完畢,協程正常終止,resume 返回 true和函數的返回值。

(2)?如果協程co的函數執行過程中,協程讓出了(調用了yield()方法),那么resume返回true和協程中調用yield傳入的參數。

(3)?如果協程co的函數執行過程中發生錯誤,resume返回false與錯誤消息。

可以看到resume無論如何都不會導致程序崩潰。它是在保護模式下執行的

2. coroutine.yield()函數

使正在執行的協程掛起,注意是執行該函數中會使協程掛起,該函數并未執行結束,下次resume()時才會執行完畢

(1)?yeild的參數會作為resume的第二個返回值

(2)?如果對該協程不是第一次執行resume,resume函數傳入的參數將會作為yield的返回值

yield()和resume()的關系如下圖

?

3. 協程狀態

suspended:掛起狀態,協程剛創建完成時或者yield之后

running????? ?:運行狀態,如果在協程的函數中調用status,傳入協程自身的句柄,那么執行到這里的時候才會返回running狀態

normal????? ? :如果協程A ?resume() 協程B時,則協程A處于的狀態為normal。在協程B的執行過程中,協程A就一直處于normal狀態。因為它這時候既不是掛起狀態、也不是運行狀態

dead??????????:結束狀態,如果一個協程發生錯誤結束或正常運行結束。那么就處于dead狀態,這時候如果調用resume()的話會直接返回false,且報錯"cannot resume dead coroutine"

4. 代碼示例

4. 1 ?協程狀態及yield()與resume()的交互

-- 打印協程1和協程2的狀態 function status()print("co1's status :"..coroutine.status(co1).." ,co2's status: "..coroutine.status(co2)) end-- 協程1 co1 = coroutine.create(function ( a )print("co1 arg is :"..a)status()-- 喚醒協程2local stat,rere = coroutine.resume(co2,"2")print("111 co2 resume's return is "..rere)status()-- 再次喚醒協程2local stat2,rere2 = coroutine.resume(co2,"4")print("222 co2 resume's return is "..rere2)local arg = coroutine.yield("6") end)-- 協程2 co2 = coroutine.create(function ( a )print("co2 arg is :"..a)status()local rey = coroutine.yield("3")print("co2 yeild's return is " .. rey)status()coroutine.yield("5") end)--主線程執行協程co1,傳入字符串“main thread arg” stat,mainre = coroutine.resume(co1,"main thread arg") status() print("last return is "..mainre)

結果及筆者的注釋:

co1 arg is :main thread arg -- 開始執行協程1,第8行 co1's status :running ,co2's status: suspended -- 協程1中,第9行,調用了status()函數 co2 arg is :2 -- 協程1中,第12行,調用了resume(),喚醒協程2,調用到24行 co1's status :normal ,co2's status: running -- 注意:此時協程1處于normal狀態,協程2處于running狀態 111 co2 resume's return is 3 -- 由于26行,協程2執行了yiled(),協程掛起,參數“3”被返回到協程1,賦值給了12行中resume()的第二個參數,在13行進行此打印 co1's status :running ,co2's status: suspended -- 此時協程1被喚醒,處于running狀態,協程2處于掛起狀態 co2 yeild's return is 4 -- 由于17行,協程2被再次喚醒,由于不是第一次調用resume(),參數“4”被賦值給上次26行的yiled()的返回值,打印出來,此時是27行的 co1's status :normal ,co2's status: running -- 同第一次,此時協程1處于normal狀態,協程2處于running狀態 222 co2 resume's return is 5 -- 由于第29行執行yield完畢,參數5作為17行的resume()的返回值,在18行進行了打印,注意此時協程2仍未結束,處于掛起狀態 co1's status :suspended ,co2's status: suspended -- 由于第19行,執行了yield(),參數“6”被返回給33行的mainre,注意:此時協程1掛起,同樣也未執行完 last return is 6 -- 最終35行進行了打印,mainre的值,也就是resume()的第二個返回值其實就是yidld()的參數

4.2 下面這段代碼摘取云風的,演示yield()和resume()的交互

function foo(a)print("foo", a)return coroutine.yield(2 * a) endco = coroutine.create(function ( a, b )print("co-body", a, b)local r = foo(a + 1)print("co-body", r)local r, s = coroutine.yield(a + b, a - b)print("co-body", r, s)return b, "end" end)print("main", coroutine.resume(co, 1, 10)) print("main", coroutine.resume(co, "r")) print("main", coroutine.resume(co, "x", "y")) print("main", coroutine.resume(co, "x", "y"))

結果及筆者的備注:

co-body 1 10 -- 協程co的第7行,此時resume()傳入的參數是賦值給了函數的 foo 2 -- 在第8行里面調用了函數foo(),執行到第2行的打印 main true 4 -- 由于函數foo()的第3行yield()執行后掛起,參數是4,作為第15行的resume()的第二個返回值,最終打印了出來,到此,第15行執行完畢 co-body r -- 第16行resume()再次喚醒協程co,接著上次yield()的地方繼續執行,參數“r"被賦值給上次yield()的返回值,在第9行打印出來 main true 11 -9 -- 在第10行yiled()后再次掛起協程co,并返回,此時參數a和b還是第一次resume()時的參數,1,10,所以yield()兩個參數分別為11,-9,作為resum()的第二個返回值,最終被打印出來,到此,第16行執行完畢 co-body x y -- 第17行resume()再次喚醒協程co,傳入的參數“x”,“y”被賦值給上次的yield()函數的返回值,即賦值給第10行的r,s,在第11行被打印出來 main true 10 end -- 協程co在第12行返回,注意此時參數b仍然是第一次resume()時的參數2,值為10,至此協程co執行結束,變為dead狀態,最終在第17行打印出來 main false cannot resume dead coroutine -- 第18行嘗試再次resume()協程co,由于協程co已經為dead狀態,所以直接返回并報錯

4.3 生產者消費者

-- 生產者協程,負責產生數據(由控制臺輸入),然后掛起協程,把值傳遞給過濾器協程 produceFunc = function()while true dolocal value = io.read() -- 等待輸入,即生產數據print("produce: ", value)coroutine.yield(value) -- 掛起本生產者協程,返回生產的值end end-- 過濾器協程,喚醒生產者協程,等待其產生數據,得到數據后,負責把數據放大100倍,然后掛起協程,把值傳遞給消費者函數 filteFunc = function(p)while true dolocal status, value = coroutine.resume(p); -- 喚醒生產者協程,直到其返回數據value = value *100 -- 把數據放大100倍print("filte: ", value)coroutine.yield(value) -- 掛起本過濾器協程,返回處理后的值end end-- 消費者,只是個函數,并非協程,while一直調用,即一直喚醒過濾器協程 consumer = function(f, p)while true dolocal status, value = coroutine.resume(f, p);--喚醒過濾器協程,參數是生產者協程print("consume: ", value) -- 打印出得到的值,即消費end end--備注: -- 1. 消費者驅動的設計,也就是消費者需要產品時找生產者請求,生產者完成生產后提供給消費者 -- 2. 這里做了中間的過濾器協程,即消費者函數找過濾器協程,過濾器協程找生產者協程,等待其返回數據,再原路返回,傳遞給消費者函數,while一直循環-- 生產者協程 producer = coroutine.create(produceFunc)--過濾器協程 filter = coroutine.create(filteFunc)-- 消費者函數,傳入過濾器協程和生產者協程 consumer(filter, producer)

結果:筆者輸入123,99做示例

123 produce: 123 filte: 12300 consume: 12300 99 produce: 99 filte: 9900 consume: 9900

?

?

?

?

總結

以上是生活随笔為你收集整理的深入理解lua的协程coroutine的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产拍拍拍拍拍拍拍拍拍拍拍拍拍 | 日韩欧美中文字幕一区二区三区 | 最新日韩精品 | 九九九九九伊人 | 精品一区二区三区蜜桃 | 免费的黄色大片 | 日韩资源站| 在线播放无码后入内射少妇 | 国产 丝袜 欧美中文 另类 | 亚洲熟妇av日韩熟妇在线 | 亚洲婷婷久久综合 | 快播av在线| 五月婷婷综合在线观看 | 国产精品99久久久久久大便 | 黄网址在线 | 夜夜躁狠狠躁日日躁av | 欧美少妇一级片 | 欧洲精品一区二区 | 国产乱妇无码大片在线观看 | 黑人干亚洲 | 久久久久女人精品毛片九一 | 男女做爰真人视频直播 | 国产老女人乱淫免费 | 国产三级在线免费 | 久久草视频在线 | 亚洲精品久久久 | 欧美一区二区三区系列电影 | 欧美黄色高清视频 | 国产精品视频一 | 久久中文av | 欧美色狠 | 麻豆av一区 | 欧美日韩一二三区 | 99在线观看免费视频 | 国产成人精品一区二区在线观看 | 国产亚洲久久 | 日韩欧美成人一区二区 | 国产精品亚洲一区二区三区在线观看 | 午夜不卡福利 | 成人一区二区三区 | 欧美jjzz| a视频| 久久精品高清视频 | 日韩高清免费av | 久久性精品 | 小萝莉末成年一区二区 | 韩国三级中文字幕 | 国产伦视频 | 久久婷婷av| 美日韩一区 | 亚洲九九色 | 国内精品免费视频 | 国产中文字幕在线 | 性色av蜜臀av浪潮av老女人 | 台湾av在线 | 成人免费片 | 96精品| 爱情岛论坛自拍亚洲品质极速最新章 | 亚洲欧美伦理 | 欧美69久成人做爰视频 | 黑森林av| 曰本黄色大片 | 国产大片网站 | 日韩精品一区在线视频 | 青青艹在线观看 | 天天干天天色综合 | 日本三级视频在线播放 | 国产91熟女高潮一区二区 | 久久精品国产一区二区 | 乳揉みま痴汉4在线播放 | 91精品国产91综合久久蜜臀 | 玖草视频在线观看 | 男人与雌性宠物交啪啪 | 1024金沙人妻一区二区三区 | 一本加勒比hezyo黑人 | 色婷婷av一区二区三区四区 | 欧洲国产精品 | 欧洲mv日韩mv国产 | 这里只有精品在线播放 | mm1313亚洲精品 | 尹人香蕉网 | 狠狠干婷婷 | 看片日韩 | 亚洲免费观看高清 | 成人国产精品视频 | 欧美中文视频 | 久草影视网 | 天天透天天干 | 亚洲国产精 | 我不卡一区二区 | 精品中文字幕在线观看 | 91麻豆视频在线观看 | 色午夜婷婷 | 九九av在线 | 手机看片福利在线 | 天天看夜夜操 | 日韩av高清在线观看 | 久久精品a | 久久精品国产亚洲av麻豆蜜芽 |