摘要:比如里可以直接把執(zhí)行權(quán)交給,而完全不知情。雖然不能和多線程相比,但是效果是類(lèi)似的。對(duì)于多線程的代碼,是任何一行代碼都可能與其他線程并行。加上協(xié)程之間有共享狀態(tài)的話(huà),一定程度上會(huì)產(chǎn)生類(lèi)似多線程的并發(fā)讀寫(xiě)狀態(tài)的。
前面講generator是顯式的協(xié)程的時(shí)候缺一個(gè)例子,現(xiàn)在補(bǔ)上
def parent_generator(): print("hello") yield from sub_generator() print("world") def sub_generator(): yield 1 gen = parent_generator() gen.send(None) gen.send(None)
這里可以看出parent_generator為了在hello和world之間中斷,必須顯式的用yield from把控制權(quán)從自己手里轉(zhuǎn)交給調(diào)用者。如果parent_generator沒(méi)有使用yield,那么sub_generator里即使有yield也無(wú)法使得parent_generator的執(zhí)行權(quán)轉(zhuǎn)交出去。所以從視覺(jué)上可以一步了然的指導(dǎo)一個(gè)函數(shù)中哪些調(diào)用是產(chǎn)生了switch的,哪些是肯定順序執(zhí)行的。有一點(diǎn)類(lèi)似Haskell里給所有I/O操作加類(lèi)型標(biāo)簽的味道。
from greenlet import greenlet def parent(): print("hello") sub() print("world") def sub(): greenlet.getcurrent().parent.switch() g = greenlet(parent) g.switch() print("here is switched from the sub generator") g.switch()
這段代碼的輸出是
hello here is switched from the sub generator world
改用greenlet之后,協(xié)程之間的跳轉(zhuǎn)就變得非常隨意了。比如sub里可以直接把執(zhí)行權(quán)交給main,而parent完全不知情。從視覺(jué)上來(lái)看parent的實(shí)現(xiàn)里完全不能知道在sub內(nèi)部發(fā)生了switch。
雖然不能和多線程相比,但是效果是類(lèi)似的。對(duì)于多線程的代碼,是任何一行代碼都可能與其他線程并行。類(lèi)似greenlet的隱式的協(xié)程,雖然不是每一行代碼都可能產(chǎn)生switch。雖然產(chǎn)生switch的地方其實(shí)和用yield寫(xiě)是一樣多,而且也是一樣固定的。但是因?yàn)槿鄙購(gòu)?qiáng)制的yield,使得在不閱讀被調(diào)用函數(shù)內(nèi)部的實(shí)現(xiàn)的前提下,無(wú)法提前知道這個(gè)調(diào)用是否會(huì)產(chǎn)生執(zhí)行權(quán)的遷移。加上協(xié)程之間有共享狀態(tài)的話(huà),一定程度上會(huì)產(chǎn)生類(lèi)似多線程的并發(fā)讀寫(xiě)狀態(tài)的bug。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/37394.html
摘要:如果說(shuō)相比來(lái)說(shuō),是一種隱式的協(xié)程的話(huà),提供的就更加隱式了。通過(guò)調(diào)用可以知道這個(gè)鏈表目前的大小。正式因?yàn)闆](méi)有把底層的協(xié)程直接控制接口開(kāi)放,而是強(qiáng)買(mǎi)強(qiáng)賣(mài)了一個(gè),所以想要在像那樣隨心所欲的操縱協(xié)程還是頗費(fèi)一番周折的。 如果說(shuō)greenlet相比generator來(lái)說(shuō),是一種隱式的協(xié)程的話(huà),stackless python提供的api就更加隱式了。 import stackless def...
摘要:從到到再到,各家的語(yǔ)法都不太一樣。底層的實(shí)現(xiàn)是,看名字應(yīng)該是的意思。然后在這個(gè)基礎(chǔ)上實(shí)現(xiàn)了的和的。的的語(yǔ)法風(fēng)格也是類(lèi)似所以從語(yǔ)法上來(lái)說(shuō)就三類(lèi)這樣強(qiáng)制要求的為代表的隱式控制權(quán)的為代表強(qiáng)買(mǎi)強(qiáng)賣(mài)編碼風(fēng)格的 從generator到greenlet到stackless再到pypy,各家的語(yǔ)法都不太一樣。pypy底層的實(shí)現(xiàn)是continulet,看名字應(yīng)該是continuation的意思。然后在這...
摘要:協(xié)程其實(shí)就是一個(gè)可中途中斷,由外部來(lái)控制執(zhí)行進(jìn)程的函數(shù)。這些第三方的選擇的共同特點(diǎn)是協(xié)程的都是隱式的。這就是顯示控制和隱式控制的區(qū)別。本文討論的協(xié)程就是這一種,后面會(huì)逐漸展開(kāi)到如何利用這種顯示控制的協(xié)程來(lái)解決阻塞和流程阻塞的問(wèn)題。 Python官方的實(shí)現(xiàn)里,協(xié)程只有g(shù)enerator這一招。協(xié)程其實(shí)就是一個(gè)可中途中斷,由外部來(lái)控制執(zhí)行進(jìn)程的函數(shù)。除了官方的generator,還有很多第...
摘要:常規(guī)版本的的是不可以被持久化保存的。在流程被阻塞的時(shí)候比如需要審批老板不在把協(xié)程持久化成入庫(kù),等流程不再阻塞的時(shí)候把協(xié)程重新從數(shù)據(jù)庫(kù)里拉起來(lái)繼續(xù)執(zhí)行。 常規(guī)版本的Python的generator是不可以被持久化保存的。但是stackless和pypy這兩個(gè)修改版本的Python解釋器可以。下面這段代碼演示了如何把一個(gè)執(zhí)行中的函數(shù)持久化保存,然后過(guò)段時(shí)間再把函數(shù)從上次執(zhí)行到的地方原樣拉起...
摘要:特別是最火的協(xié)程框架也無(wú)法保存狀態(tài),讓人非常惋惜。但是因?yàn)闂5谋旧頍o(wú)法持久化,所以也就無(wú)法持久化。其難度在于,假設(shè)整個(gè)要持久化的調(diào)用棧全部都是內(nèi)的,比如純的。采取的是暴力地把整個(gè)棧區(qū)域拷貝到上的方式來(lái)保存其狀態(tài)。 python主流的協(xié)程實(shí)現(xiàn)有五種: cPython的generator cPython的greenlet cPython的fibers stackless python ...
閱讀 3803·2021-11-17 09:33
閱讀 2020·2021-10-26 09:51
閱讀 1538·2021-09-29 09:44
閱讀 1688·2019-08-30 15:55
閱讀 1455·2019-08-30 15:52
閱讀 2333·2019-08-30 15:43
閱讀 3442·2019-08-29 17:00
閱讀 2310·2019-08-29 16:23