摘要:怎么記錄呢這里就可以回到上面我們需要了解的幾個棧操作了。這個時候,如果函數(shù)執(zhí)行完了想去執(zhí)行函數(shù)的時候,就按照這個流程再保存,然后再把剛才存放的函數(shù)給復(fù)制到棧中。
gevent文檔:that uses greenlet to provide a high-level synchronous API.
意思是:使用greenlet來提供高級同步API。
那greenlet又是怎樣一種機制呢?這個后面會稍微簡單的講一下原理,不過在后續(xù)的幾篇會著重分析它的源碼。在開始之前先看看提到的幾個關(guān)鍵字『高級』、『同步』,高級不高級暫時還不知道,畢竟在實際生產(chǎn)環(huán)境中才看得到效果。而同步這個概念,不知道大家理解深不深刻,總之我當(dāng)初理解不是很深刻,所以遇到了就聊聊唄!
同步不明白為什么會叫同步,總是讓我有一種錯覺,讓我聯(lián)想到的第一個詞匯就是同時進行。不知道大家是不是和我一樣,至少我看到同步是不會去想到它的正確意思。我曾一度懷疑是不是翻譯錯了,但是在質(zhì)疑別人錯之前,應(yīng)該先質(zhì)疑一下自己。所以我開始懷疑我的語文沒學(xué)好,然后我去查了一下漢語詞典,結(jié)果就悲劇了,我已經(jīng)開始懷疑我的人生了。 %>_<%
同步:指兩個或兩個以上隨時間變化的量在變化過程中保持一定的相對關(guān)系。
《光明日報》1984.6.2:“城市改革的步子要加快,要從解決國家與企業(yè)、企業(yè)與職工的關(guān)系入手,把適合于當(dāng)前情況的各項改革措施初步配起套來,同步進行。
從上面引用的話應(yīng)該可以看出,國家與企業(yè)、企業(yè)與職工,都是兩個相對的關(guān)系,有著各自的利益。但是他們必須合作才能完成一個共同目標(biāo),例如買票看電影。這個場景有兩個動作需要完成,一個出票、一個買票,只有出票才能買票,并且這個買票的人還只能傻等,不能做其他事。
同步真心不是同時進行,所以還是要多讀書??!尤其是語文!
為什么這里會講到同步呢?其實不講也是可以的,和理解greenlet原理沒有多大關(guān)系,但是和理解gevent的特性有那么點關(guān)系,因為聽別人說gevent能夠讓你用這種同步的代碼寫出異步的感覺,同步的代碼好理解也好處理。我沒有驗證過,所以我也不知道,真正的原因是感覺這個概念很容易混淆,所以就來講講了。
Greenlet還記得在協(xié)程篇中學(xué)習(xí)的嗎?花了較長篇幅講協(xié)程及從其子例程演變的過程。而greenlet就是python中實現(xiàn)Coroutine「協(xié)程」的一個基礎(chǔ)庫。前面我們了解了協(xié)程的相關(guān)概念及思想,但我們還不知道它在底層是怎樣實現(xiàn)的。只知道它有個特別的地方,就是能夠和進程、線程一樣保存上下文,那協(xié)程的上下文是怎樣保存的呢?
源碼初探typedef struct _greenlet { PyObject_HEAD char* stack_start; char* stack_stop; char* stack_copy; intptr_t stack_saved; struct _greenlet* stack_prev; struct _greenlet* parent; PyObject* run_info; struct _frame* top_frame; int recursion_depth; PyObject* weakreflist; PyObject* exc_type; PyObject* exc_value; PyObject* exc_traceback; PyObject* dict; } PyGreenlet;
上面給出的是greenlet的結(jié)構(gòu)體定義,有興趣的可以去下一份源代碼看看,里面也有很好的解釋。
這里我們主要了解一下關(guān)于堆棧的幾個操作,從命名規(guī)則就可以找到我們想要的東西,就是它們幾個了:stack_start、stack_stop、stack_copy、stack_saved。
其實仔細想想,你會發(fā)現(xiàn)非常的簡單。假設(shè)有『函數(shù)A』和『函數(shù)B』,『函數(shù)A』進棧執(zhí)行到一半的時候需要調(diào)用『函數(shù)B』,沒事這個簡單,我們可以將『函數(shù)B』進棧(圖stack-01)。
好了『函數(shù)B』進棧了,可它現(xiàn)在又想調(diào)用『函數(shù)A』了,怎么辦?讓『函數(shù)A』進棧(圖stack-02),這個其實就是普通的函數(shù)調(diào)用,此『函數(shù)A』并不是第一次進棧的那個『函數(shù)A』,而是重新在棧中創(chuàng)建的一個實例,該實例的數(shù)據(jù)并不是之前『函數(shù)A』的數(shù)據(jù),可是我想要之前『函數(shù)A』的數(shù)據(jù)啊!所以這個方法并不能實現(xiàn)我們想要的切換。
那怎樣才能做到我們想要的呢?很簡單,既然『函數(shù)B』完成了當(dāng)前的任務(wù),它就應(yīng)該退出來了,但并不是直接出棧,而是通過某種方式將現(xiàn)有的state給記錄下來,方便下次用到的時候能夠找到。怎么記錄呢?這里就可以回到上面我們需要了解的幾個棧操作了。
首先,每個greenlet都有屬于它們自己的stack_start和stack_stop,通過這兩個可以找到你準(zhǔn)備出棧的greenlet也就是『函數(shù)B』的所有數(shù)據(jù),之后再調(diào)用PyMem_Realloc這個方法,就可以在heap中創(chuàng)建一個內(nèi)存空間用來存放『函數(shù)B』,地址為stack_copy,大小為stack_saved字節(jié),通過這兩個就可以定位到你存放的『函數(shù)B』的數(shù)據(jù)了(圖stack-03)。
之后變成下面(圖stack-04)這樣了。這個時候,如果『函數(shù)A』執(zhí)行完了想去執(zhí)行『函數(shù)B』的時候,就按照這個流程再保存,然后再把剛才存放的『函數(shù)B』給復(fù)制到C棧中。因為已經(jīng)知道了stack_copy和stack_saved,所以也就不怕找不到它了。
整個greenlet切換流程大概就是這個樣子了,不過到了這里不知道大家會不會有些疑問,雖然保存了stack_copy和stack_saved,但是『函數(shù)B』已經(jīng)出棧了,不是就沒有這個對象了嗎?那這兩個參數(shù)是由誰來保存呢?
其實這個對象從來就沒有被銷毀,只要這個greenlet沒有正常退出,它的對象就一直都存在著,因為Greenlet還維護著一個鏈表,它保存著所有沒有徹底退出的greenlet對象,『函數(shù)B』出棧并不是完全退出了,只是不參與這次行動。具體的細節(jié)就要等到下一篇或者下下篇的源碼剖析來講解了。
因為最近工作比較忙,換了一個部門,加上之前對源碼理解不夠,也就不敢隨便發(fā)表。當(dāng)然現(xiàn)在發(fā)表的也不敢說絕對正確,這些僅僅是我個人的理解,歡迎大神來指正。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/37354.html
摘要:不過不管怎樣,就當(dāng)多學(xué)習(xí)了一些其他知識,況且分析源碼肯定少不了對這些知識的了解。官方文檔描述里面提到了,在這個模塊中指的就是,一般稱它為方法列表。返回一個指向它創(chuàng)建的模塊對象的指針。 showImg(http://young-py.github.io/imgs/yyzt3.jpg); 在greenlet篇中只是簡單講述了一下greenlet原理,不知道有沒有人對源碼感興趣的,不過我還...
摘要:一旦有事件產(chǎn)生可能是一次出現(xiàn)好多個事件,就會按照優(yōu)先級依次調(diào)用每個事件的回調(diào)函數(shù)。注意,是有超時的,所以一些無法以文件描述符的形式存在的事件也可以有機會被觸發(fā)。 這一篇主要想跟大家分享一下 Gevent 實現(xiàn)的基礎(chǔ)邏輯,也是有同學(xué)對這個很感興趣,所以貼出來跟大家一起分享一下。 Greenlet 我們知道 Gevent 是基于 Greenlet 實現(xiàn)的,greenlet 有的時候也被...
摘要:隨著我們對于效率的追求不斷提高,基于單線程來實現(xiàn)并發(fā)又成為一個新的課題,即只用一個主線程很明顯可利用的只有一個情況下實現(xiàn)并發(fā)。作為的補充可以檢測操作,在遇到操作的情況下才發(fā)生切換協(xié)程介紹協(xié)程是單線程下的并發(fā),又稱微線程,纖程。 引子 之前我們學(xué)習(xí)了線程、進程的概念,了解了在操作系統(tǒng)中進程是資源分配的最小單位,線程是CPU調(diào)度的最小單位。按道理來說我們已經(jīng)算是把cpu的利用率提高很多了。...
摘要:所以與多線程相比,線程的數(shù)量越多,協(xié)程性能的優(yōu)勢越明顯。值得一提的是,在此過程中,只有一個線程在執(zhí)行,因此這與多線程的概念是不一樣的。 真正有知識的人的成長過程,就像麥穗的成長過程:麥穗空的時候,麥子長得很快,麥穗驕傲地高高昂起,但是,麥穗成熟飽滿時,它們開始謙虛,垂下麥芒。 ——蒙田《蒙田隨筆全集》 上篇論述了關(guān)于python多線程是否是雞肋的問題,得到了一些網(wǎng)友的認可,當(dāng)然也有...
摘要:協(xié)程,又稱微線程,纖程。最大的優(yōu)勢就是協(xié)程極高的執(zhí)行效率。生產(chǎn)者產(chǎn)出第條數(shù)據(jù)返回更新值更新消費者正在調(diào)用第條數(shù)據(jù)查看當(dāng)前進行的線程函數(shù)中有,返回值為生成器庫實現(xiàn)協(xié)程通過提供了對協(xié)程的基本支持,但是不完全。 協(xié)程,又稱微線程,纖程。英文名Coroutine協(xié)程看上去也是子程序,但執(zhí)行過程中,在子程序內(nèi)部可中斷,然后轉(zhuǎn)而執(zhí)行別的子程序,在適當(dāng)?shù)臅r候再返回來接著執(zhí)行。 最大的優(yōu)勢就是協(xié)程極高...
閱讀 3389·2021-11-23 09:51
閱讀 1079·2021-09-26 09:55
閱讀 4101·2021-09-22 14:58
閱讀 1768·2021-09-08 09:35
閱讀 1156·2021-08-26 14:16
閱讀 950·2019-08-23 18:17
閱讀 2179·2019-08-23 16:45
閱讀 760·2019-08-23 15:55