日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Lua coroutine 不一样的多线程编程思路

發(fā)布時(shí)間:2025/5/22 61 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lua coroutine 不一样的多线程编程思路 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上周末開始看《Lua程序設(shè)計(jì)》第二版,目前體會到其中比較有趣的有兩點(diǎn),一是強(qiáng)大的table數(shù)據(jù)結(jié)構(gòu),另外就是coroutine。也許Lua中的coroutine是一種很好的設(shè)計(jì)模式,但我初步的體會還是沒想到其他語言和場合能非常適合用到coroutine的場景。

一、簡介

協(xié)同程序與線程差不多,也就是一條執(zhí)行序列,擁有自己獨(dú)立的棧,局部變量和指令指針,同時(shí)又與其它協(xié)同程序共享全局變量和其它大部分東西。線程與協(xié)同程序的主要區(qū)別在于,一個(gè)具有多線程的程序可以同時(shí)運(yùn)行幾個(gè)線程,而協(xié)同程序卻需要彼此協(xié)作地運(yùn)行。就是說,一個(gè)具有多個(gè)協(xié)同程序的程序在任何時(shí)刻只能運(yùn)行一個(gè)協(xié)同程序,并且正在運(yùn)行的協(xié)同程序只會在其顯示地掛起時(shí),它的執(zhí)行才會暫停。

如:

co = coroutine.create(function () for i=1,10 do print("co", i) coroutine.yield() end end)

從主線程調(diào)用
coroutine.resume(co)
會依次打印1到10

二、原理探析

  • coroutine創(chuàng)建的所謂的“線程”都不是真正的操作系統(tǒng)的線程,實(shí)際上是通過保存stack狀態(tài)來模擬的。
  • 由于是假的線程,所以切換線程的開銷極小,同時(shí)創(chuàng)建線程也是輕量級的,new_thread只是在內(nèi)存新建了一個(gè)stack用于存放新coroutine的變量,也稱作lua_State

LUA_API lua_State *lua_newthread (lua_State *L)

  • 調(diào)用yield()當(dāng)前線程交出控制權(quán),同時(shí)還可以通過stack返回參數(shù)。調(diào)用resume的線程(可理解為主線程)獲得返回的參數(shù)。
  • Lua yield()和Java中的Thread.yield()有點(diǎn)相似,但是區(qū)別更大。Java中的yield調(diào)用后只是將當(dāng)前CPU切換到另外一個(gè)線程,CPU可能隨時(shí)會繼續(xù)回到線程執(zhí)行。
  • 我更傾向于把Lua中的yield()和resume()和Java中的wait()和notify()來對比。它們表現(xiàn)的行為基本一致。
  • 關(guān)于stack實(shí)現(xiàn)也可參看Yufeng(Erlang高手)的分析文章 lua coroutine是如何實(shí)現(xiàn)的?

三、Why coroutine?

上面對coroutine有個(gè)基本的了解,因此大家都會象我一樣去想,為什么要用coroutine?先研究下優(yōu)點(diǎn)

  • 每個(gè)coroutine有自己私有的stack及局部變量。
  • 同一時(shí)間只有一個(gè)coroutine在執(zhí)行,無需對全局變量加鎖。
  • 順序可控,完全由程序控制執(zhí)行的順序。而通常的多線程一旦啟動,它的運(yùn)行時(shí)序是沒法預(yù)測的,因此通常會給測試所有的情況帶來困難。所以能用coroutine解決的場合應(yīng)當(dāng)優(yōu)先使用coroutine。

再看缺點(diǎn),研究coroutine缺點(diǎn)之前,我尋找了一下Lua中為什么實(shí)現(xiàn)coroutine的一些說明。在巴西人寫的paper Coroutines in Lua(pdf)中解釋了幾個(gè)原因:

  • Lua是ANSI C實(shí)現(xiàn)的,ANSI C并不包含thread的實(shí)現(xiàn),因此如果要在Lua增加thread的支持就要使用操作系統(tǒng)本地的實(shí)現(xiàn),這樣會造成通用的問題。同時(shí)也會使Lua變得臃腫。因此Lua選擇了在ANSI C上實(shí)現(xiàn)的coroutine。
  • Lua主要設(shè)計(jì)目的之一是給C調(diào)用,如果Lua內(nèi)部又有多線程實(shí)現(xiàn)的話會造成C調(diào)用狀態(tài)的混亂,而只提供coroutine層面的掛起則可以保持狀態(tài)的一致性。

以上這些理由都是基于Lua特殊的原因而使用的,并不是很通用的原因。我們也了解到,coroutine實(shí)際上是一種古老的設(shè)計(jì)模式,它在60年代就已經(jīng)定型,但是現(xiàn)代語言很少有重視這個(gè)特性,目前可以舉例的有Windows的fibers, Python的generators

四、Lua coroutine和Erlang

上面優(yōu)點(diǎn)有1條沒展開,就是每個(gè)coroutine有自己私有的stack及內(nèi)存變量空間。因此可以認(rèn)為coroutine和Erlang中的process是非常相似的。但是coroutine只能同時(shí)只有一個(gè)在執(zhí)行,如果能讓他多個(gè)同時(shí)跑,我覺得就和Erlang非常相似了。

《Lua程序設(shè)計(jì)》第二版30.2介紹的一種實(shí)現(xiàn)方法,讓多個(gè)c threads啟動,然后每個(gè)c thread啟動一個(gè)coroutine(類似Erlang process),然后通過stack傳遞變量值(類似Erlang process message),這樣就可以實(shí)現(xiàn)一個(gè)類似Erlang的process模型了。由于coroutine實(shí)際上可以用任何語言實(shí)現(xiàn),那其他語言應(yīng)該也可實(shí)現(xiàn)同樣這種設(shè)計(jì)方法。

五、Lua其他

Lua目前主要用在游戲編程領(lǐng)域,通常的觀點(diǎn)Lua是“膠水語言”。用來把各個(gè)模塊化的功能粘合起來。就我目前閱讀的一些代碼來看,C和Lua通常是混合在一起的,并沒有明確的邊界。對于我一個(gè)外行的眼光看來我分不清哪些是在做C的事情,哪些是在調(diào)用Lua。特別是這個(gè)“膠水”如果放得太多,系統(tǒng)中各個(gè)模塊的獨(dú)立性將會受到影響。比如云風(fēng)的這篇Lua 不是 C++也提到,“這屬于過厚的粘合層,是絕對需要拋棄的”。

另外Code@Pig一篇[網(wǎng)游設(shè)計(jì)] 一點(diǎn)感想也提到要簡化調(diào)用,我總結(jié)它的觀點(diǎn)主要兩點(diǎn):

  • 不要存在冗余的關(guān)系,給一個(gè)部分負(fù)責(zé)管理就好。(由Lua/python來管理)
  • 粘合層(Lua/python接口)不要過胖,我們可以通過引入一個(gè)“間接層”來把粘合層做“薄”
  • 雖然Lua的高效和精簡的設(shè)計(jì)讓人贊譽(yù)有加,但是它的性能排名并不高,和Python大致在同一個(gè)級別。另外“膠水語言”的定位也妨礙了它在更多領(lǐng)域的發(fā)展。

    轉(zhuǎn)載于:https://blog.51cto.com/timyang/307675

    《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

    總結(jié)

    以上是生活随笔為你收集整理的Lua coroutine 不一样的多线程编程思路的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。