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