莊周夢(mèng)蝶

          生活、程序、未來
             :: 首頁(yè) ::  ::  :: 聚合  :: 管理

          ??? Actor、CoroutineContinuation這三個(gè)概念由于并發(fā)的受關(guān)注而被經(jīng)常提到,這里主要想談下這三者的區(qū)別和聯(lián)系,以便更好的區(qū)分問題領(lǐng)域和討論。首先,Actor和Coroutine在我看來是兩種并發(fā)模型,僅針對(duì)于并發(fā)這個(gè)領(lǐng)域,而Continuation則是程序設(shè)計(jì)領(lǐng)域的一個(gè)概念,相比于Actor和Coroutine是一個(gè)更基礎(chǔ)的概念。

          ??? 那么,什么是Continuation?這個(gè)要從表達(dá)式的求值說起。一個(gè)表達(dá)式的求值可以分為兩個(gè)階段:“What to evaluate?”和“What to do with the value”,“What to do with the value”就是計(jì)算的Continuation。以下面這段代碼為例:
          if?x<3?then
          ???
          return?x+1
          else
          ???
          return?x
          end

          ??? 考察其中的表達(dá)式x<3,這個(gè)表達(dá)式就是“what to evaluate?”,代表你將計(jì)算的東西,然后根據(jù)x<3的結(jié)果決定是執(zhí)行x+1還是直接返回x,這個(gè)根據(jù)x<3的值來決定下一步的過程就是這個(gè)表達(dá)式的Continuation,也就是"what to do with the value"。怎么得到某個(gè)表達(dá)式的Continuation呢?在支持Continuation的語(yǔ)言里提供了call-with-current-continuation的函數(shù),通常簡(jiǎn)稱為call/cc,使用這個(gè)函數(shù)你就可以在任何代碼中得到Continuation。進(jìn)一步,continuation有什么作用呢?它可以做的事情不少,如nonlocal exits、回溯、多任務(wù)的實(shí)現(xiàn)等等。例如在scheme中沒有break語(yǔ)句,就可以用call/cc實(shí)現(xiàn)一些此類高級(jí)的控制結(jié)構(gòu):

          (call/cc?(lambda?(break)
          ????????(
          for-each?(lambda?(x)?(if?(<?x?0)?(break?x)))
          ????????????????
          '(99?88?-77?66?55))
          ????????#t))


          ??? 上面這段代碼查找列表(99 88 -77 66 55)中的負(fù)數(shù),當(dāng)查找到的時(shí)候馬上從迭代中退出并返回該值,其中的break就是一個(gè)continuation。剛才還提到continuation可以實(shí)現(xiàn)回溯,那么就可以實(shí)現(xiàn)一個(gè)窮舉的機(jī)器出來用來搜索解空間,也就是類似Prolog中的回溯機(jī)制,在SICP這本書里就介紹了如何用call/cc實(shí)現(xiàn)一個(gè)簡(jiǎn)單的邏輯語(yǔ)言系統(tǒng)。更著名的就是神奇的amb操作符,有興趣可以看看這里
          ????
          ???? 接下來我們來看看如何continuation實(shí)現(xiàn)多任務(wù),在Continuation的維基百科里給了一段代碼來展示如何用scheme來實(shí)現(xiàn)coroutine,我稍微修改了下并添加了注釋:
          ;;continuation棧,保存了等待執(zhí)行的continuation
          (define?call/cc?call-with-current-continuation)
          (define?*queue*?'())

          (define?(empty-queue?)
          ????????(null??*queue*))

          (define?(enqueue?x)
          ????????(set!?*queue*?(append?*queue*?(list?x))))

          (define?(dequeue)
          ????????(let?((x?(car?*queue*)))
          ??????????????(set!?*queue*?(cdr?*queue*))
          ?????????x))
          ;;啟動(dòng)協(xié)程
          (define?(resume?proc)
          ???????(call/cc
          ?????????(lambda?(k)
          ???????????;;保存當(dāng)前continuation,執(zhí)行proc
          ???????????(enqueue?k)
          ???????????(proc))))
          ;;讓出執(zhí)行權(quán)
          (define?(yield)
          ?????(call/cc
          ??????(lambda?(k)
          ?????????;;保存當(dāng)前continuation,彈出上一次執(zhí)行的cont并執(zhí)行
          ????????(enqueue?k)
          ????????((dequeue)))))
          ;;停止當(dāng)前協(xié)程或者當(dāng)沒有一個(gè)協(xié)程時(shí)停止整個(gè)程序,最簡(jiǎn)單的調(diào)度程序
          (define?(thread-exit)
          ?????(if?(empty-queue?)
          ?????????(exit)
          ?????????((dequeue))))
          (注:scheme以分號(hào)開頭作為注釋)

          ???? 這其實(shí)就是一個(gè)coroutine的簡(jiǎn)單實(shí)現(xiàn),context的保存、任務(wù)的調(diào)度、resume/yield原語(yǔ)……樣樣俱全。使用起來類似這樣,下面這段程序輪流打印字符串:
          (define?(display-str?str)
          ????????(lambda()
          ?????????(let?loop()
          ??????????????(display?str)
          ??????????????(newline)
          ??????????????(yield)
          ??????????????(loop))))

          ;;;創(chuàng)建兩個(gè)協(xié)程并啟動(dòng)調(diào)度器
          (resume?(display-str?"This?is?AAA"))
          (resume?(display-str?"Hello?from?BBB"))
          (thread-exit)

          ???? 任務(wù)非常簡(jiǎn)單,打印下傳入的字符串并換行,然后讓出執(zhí)行權(quán)給另一個(gè)任務(wù)執(zhí)行,因此輸出:
          This?is?AAA
          Hello?from?BBB
          This?is?AAA
          Hello?from?BBB
          This?is?AAA
          Hello?from?BBB
          This?is?AAA
          Hello?from?BBB
          ……

          ??? 談了這么多continuation的應(yīng)用,事實(shí)上我想說明的是continuation可以用來實(shí)現(xiàn)協(xié)程,Ruby 1.9中call/cc和Fiber的實(shí)現(xiàn)(在cont.c)大體是一樣的同樣說明了這一點(diǎn)。

          ???? 接下來我們討論下Actor和Coroutine的關(guān)系,上面提到Actor是一種并發(fā)模型,我更愿意稱之為一種編程風(fēng)格,Actor跟message passing、Duck Typing是一脈相承的。Actor風(fēng)格是可以這么描述:將物理世界抽象成一個(gè)一個(gè)的Actor,Actor之間通過發(fā)送消息相互通信,Actor不關(guān)心消息是否能被接收或者能否投遞到,它只是簡(jiǎn)單地投遞消息給其他actor,然后等待應(yīng)答。Actor相比于Coroutine是一種更高層次的抽象,它提供的receive和pattern match的原語(yǔ)更接近于現(xiàn)實(shí)世界,而使用coroutine編程你還需要手工介入任務(wù)調(diào)度,這在Actor中是由一個(gè)調(diào)度器負(fù)責(zé)的。

          ??? 同樣,Actor可以用coroutine實(shí)現(xiàn),例如Ruby有個(gè)revactor項(xiàng)目,就是利用1.9引入的Fiber實(shí)現(xiàn)actor風(fēng)格的編程,它的實(shí)現(xiàn)非常簡(jiǎn)單,有興趣地可以看看,其實(shí)跟continuation實(shí)現(xiàn)coroutine類似。但是Actor并不是一定要用coroutine才能實(shí)現(xiàn),Actor是一種編程風(fēng)格,你在Java、C#、C++中同樣可以模擬這樣的方式去做并發(fā)編程,.net社區(qū)的老趙實(shí)現(xiàn)過一個(gè)簡(jiǎn)單的ActorScala的Actor實(shí)現(xiàn)是基于外部庫(kù),利用scala強(qiáng)大的元編程能力使得庫(kù)的使用像內(nèi)置于語(yǔ)言。

          ??? 總結(jié)下我想表達(dá)的:Continuation是程序設(shè)計(jì)領(lǐng)域的基礎(chǔ)概念,它可以用于實(shí)現(xiàn)coroutine式的多任務(wù),Actor是一種比之coroutine更為抽象的編程風(fēng)格,Actor可以基于Coroutine實(shí)現(xiàn)但并非必須,Actor和Coroutine都是現(xiàn)在比較受關(guān)注的并發(fā)模型。



          主站蜘蛛池模板: 应用必备| 衡东县| 广河县| 广昌县| 贵溪市| 怀来县| 广元市| 曲周县| 沙洋县| 疏勒县| 珲春市| 城步| 宁河县| 河曲县| 孟村| 正镶白旗| 慈利县| 德州市| 偃师市| 蕲春县| 太和县| 土默特右旗| 定边县| 马龙县| 寻乌县| 镇巴县| 合江县| 林口县| 探索| 祁东县| 武定县| 漠河县| 合山市| 巴里| 依兰县| 乐业县| 龙胜| 行唐县| 长春市| 南康市| 巨野县|