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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Lua 协同程序(coroutine)

發布時間:2024/4/11 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lua 协同程序(coroutine) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是協同(coroutine)?

Lua 協同程序(coroutine)與線程比較類似:擁有獨立的堆棧,獨立的局部變量,獨立的指令指針,同時又與其它協同程序共享全局變量和其它大部分東西。

協同是非常強大的功能,但是用起來也很復雜。

線程和協同程序區別

線程與協同程序的主要區別在于,一個具有多個線程的程序可以同時運行幾個線程,而協同程序卻需要彼此協作的運行。

在任一指定時刻只有一個協同程序在運行,并且這個正在運行的協同程序只有在明確的被要求掛起的時候才會被掛起。

協同程序有點類似同步的多線程,在等待同一個線程鎖的幾個線程有點類似協同。

基本語法

方法描述
coroutine.create()創建coroutine,返回coroutine, 參數是一個函數,當和resume配合使用的時候就喚醒函數調用
coroutine.resume()重啟coroutine,和create配合使用
coroutine.yield()掛起coroutine,將coroutine設置為掛起狀態,這個和resume配合使用能有很多有用的效果
coroutine.status()查看coroutine的狀態
注:coroutine的狀態有三種:dead,suspend,running,具體什么時候有這樣的狀態請參考下面的程序
coroutine.wrap()創建coroutine,返回一個函數,一旦你調用這個函數,就進入coroutine,和create功能重復
coroutine.running()返回正在跑的coroutine,一個coroutine就是一個線程,當使用running的時候,就是返回一個corouting的線程號

以下實例演示了以上各個方法的用法:

-- coroutine_test.lua 文件 co = coroutine.create(function(i)print(i);end )coroutine.resume(co, 1) -- 1 print(coroutine.status(co)) -- deadprint("----------")co = coroutine.wrap(function(i)print(i);end )co(1)print("----------")co2 = coroutine.create(function()for i=1,10 doprint(i)if i == 3 thenprint(coroutine.status(co2)) --runningprint(coroutine.running()) --thread:XXXXXXendcoroutine.yield()endend )coroutine.resume(co2) --1 coroutine.resume(co2) --2 coroutine.resume(co2) --3print(coroutine.status(co2)) -- suspended print(coroutine.running())print("----------")

以上實例執行輸出結果為:

1 dead ---------- 1 ---------- 1 2 3 running thread: 0x7fb801c05868????false suspended thread: 0x7fb801c04c88????true ----------

coroutine.running就可以看出來,coroutine在底層實現就是一個線程。

當create一個coroutine的時候就是在新線程中注冊了一個事件。

當使用resume觸發事件的時候,create的coroutine函數就被執行了,當遇到yield的時候就代表掛起當前線程,等候再次resume觸發事件。

接下來我們分析一個更詳細的實例:

function foo (a)print("foo 函數輸出", a)return coroutine.yield(2 * a) -- 返回 2*a 的值 endco = coroutine.create(function (a , b)print("第一次協同程序執行輸出", a, b) -- co-body 1 10local r = foo(a + 1)print("第二次協同程序執行輸出", r)local r, s = coroutine.yield(a + b, a - b) -- a,b的值為第一次調用協同程序時傳入print("第三次協同程序執行輸出", r, s)return b, "結束協同程序" -- b的值為第二次調用協同程序時傳入 end)print("main", coroutine.resume(co, 1, 10)) -- true, 4 print("--分割線----") print("main", coroutine.resume(co, "r")) -- true 11 -9 print("---分割線---") print("main", coroutine.resume(co, "x", "y")) -- true 10 end print("---分割線---") print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine print("---分割線---")

以上實例執行輸出結果為:

第一次協同程序執行輸出????1????10 foo 函數輸出????2 main????true????4 --分割線---- 第二次協同程序執行輸出????r main????true????11????-9 ---分割線--- 第三次協同程序執行輸出????x????y main????true????10????結束協同程序 ---分割線--- main????false????cannot resume dead coroutine ---分割線---

以上實例接下如下:

  • 調用resume,將協同程序喚醒,resume操作成功返回true,否則返回false;
  • 協同程序運行;
  • 運行到yield語句;
  • yield掛起協同程序,第一次resume返回;(注意:此處yield返回,參數是resume的參數)
  • 第二次resume,再次喚醒協同程序;(注意:此處resume的參數中,除了第一個參數,剩下的參數將作為yield的參數)
  • yield返回;
  • 協同程序繼續運行;
  • 如果使用的協同程序繼續運行完成后繼續調用 resume方法則輸出:cannot resume dead coroutine

resume和yield的配合強大之處在于,resume處于主程中,它將外部狀態(數據)傳入到協同程序內部;而yield則將內部的狀態(數據)返回到主程中。


生產者-消費者問題

現在我就使用Lua的協同程序來完成生產者-消費者這一經典問題。

local newProductorfunction productor()local i = 0while true doi = i + 1send(i) -- 將生產的物品發送給消費者end endfunction consumer()while true dolocal i = receive() -- 從生產者那里得到物品print(i)end endfunction receive()local status, value = coroutine.resume(newProductor)return value endfunction send(x)coroutine.yield(x) -- x表示需要發送的值,值返回以后,就掛起該協同程序 end-- 啟動程序 newProductor = coroutine.create(productor) consumer()

以上實例執行輸出結果為:

1 2 3 4 5 6 7 8 9 10 11 12 13 ……============================================================================================

協同程序較為難理解,現在先收集下資料,將來用到時候再做詳細學習

===============================================================================

lua的并發哲學?
實現并發:1、多線程(本質是共享內存數據、所以要同步多線程) 2、協程(本質是單線程、需要保證不阻塞)?

協程的好處:?
1、不用線程調度所以可以更充分利用cpu、?
2、不處理線程同步減少bug、?
3、不會為了效率而故意打斷邏輯上一致的代碼塊(所有有IO的地方后續的代碼都要放在回調里),?
?? 虛擬機內部在IO函數上yield和resume,回調對用戶是屏蔽的?

缺點:一個協程阻塞會堵住所有的協程,所以要特殊處理IO?

協程體系下的調度器:簡單的順序調度就可以有很高的吞吐率。?

?

一篇不錯的文章:

https://www.cnblogs.com/sifenkesi/p/3824321.html

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

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

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