<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python異步編程和事件驅(qū)動(dòng)

          共 3114字,需瀏覽 7分鐘

           ·

          2022-01-04 19:52


          1. 異步編程

          [1] 同步和異步描述的是進(jìn)程/線程的調(diào)用方式

          同步和異步

          • 同步調(diào)用指的是線程發(fā)起調(diào)用后,一直等待調(diào)用返回后才繼續(xù)執(zhí)行下一步操作,這并不代表CPU在這段時(shí)間內(nèi)也會(huì)一直等待,操作系統(tǒng)多半會(huì)切換到另一個(gè)線程上去,等到調(diào)用返回后再切換回原來(lái)的線程。
          • 異步就相反,發(fā)起調(diào)用后,線程繼續(xù)向下執(zhí)行,當(dāng)調(diào)用返回后,通過(guò)某種手段來(lái)通知調(diào)用者。

          解釋和說(shuō)明

          • 我們需要注意同步和異步過(guò)程中的調(diào)用返回,指的是內(nèi)核進(jìn)程將數(shù)據(jù)復(fù)制到調(diào)用進(jìn)程。上面說(shuō)的順序式編程里面,通常調(diào)用就是同步的,上一步執(zhí)行結(jié)束之后才會(huì)執(zhí)行下一步。而異步編程中,如果遇到等待的操作,會(huì)繼續(xù)往下執(zhí)行,直到請(qǐng)求返回結(jié)果在進(jìn)行處理。

          • 寫(xiě)一個(gè)使用多線程或多進(jìn)程抓取網(wǎng)站內(nèi)容的爬蟲(chóng),但由于網(wǎng)絡(luò)請(qǐng)求或?qū)Ψ骄W(wǎng)站等問(wèn)題,導(dǎo)致某段時(shí)間內(nèi)的請(qǐng)求網(wǎng)站請(qǐng)求很慢。即使設(shè)置的超時(shí)時(shí)間,那么在超時(shí)時(shí)間到來(lái)之前,這些進(jìn)程或線程都是一個(gè)等待的狀態(tài),什么也干不了。

          • 而異步編程就很適合使用在如上的場(chǎng)景中,它可以通過(guò)切換任務(wù)的方式盡量減少閑置時(shí)間。如遇到等待的請(qǐng)求就先回跳過(guò)并執(zhí)行下一個(gè)請(qǐng)求,等執(zhí)行完成之后再回到這個(gè)請(qǐng)求。如果還是沒(méi)有就緒,就切換到下下一個(gè)請(qǐng)求。

          [2] 同步和異步編程模型解釋及其圖示說(shuō)明

          單線程的同步模型

          • 在一個(gè)時(shí)刻,只能有一個(gè)任務(wù)在執(zhí)行,并且前一個(gè)任務(wù)結(jié)束后一個(gè)任務(wù)才能開(kāi)始。如果任務(wù)都能按照事先規(guī)定好的順序執(zhí)行,最后一個(gè)任務(wù)的完成意味著所有任務(wù)都完成。

          多線程/多進(jìn)程的同步模型

          • 每個(gè)任務(wù)都在單獨(dú)的線程/進(jìn)程中完成,且都是由操作系統(tǒng)來(lái)管理的。如果在多核CPU的系統(tǒng)里面,它們可能會(huì)相互獨(dú)立的運(yùn)行,而在單核中會(huì)交替的運(yùn)行。

          異步編程模型

          • 這個(gè)任務(wù)是在單線程的控制下任務(wù)交錯(cuò)完成的,相對(duì)于多線程或多進(jìn)程簡(jiǎn)單很多,沒(méi)有了內(nèi)容復(fù)制、資源傳遞的問(wèn)題。而且,程序的控制權(quán)完全在我們手里,而不會(huì)被操作系統(tǒng)收回自行處理。

          • 在這種異步編程模型,開(kāi)發(fā)者只需要將任務(wù)組織成為一個(gè)序列,交替的小步完成。每一個(gè)異步調(diào)用需要足夠的小,當(dāng)然不能耗時(shí)太久。

          • 可以看到下一圖中的這種模型,并沒(méi)有看到異步編程的太多的優(yōu)勢(shì)的,而且線程之間的切換還會(huì)帶來(lái)額外的開(kāi)銷(xiāo)。異步編程,適應(yīng)于那些任務(wù)強(qiáng)制等待或者阻塞的時(shí)候,才能發(fā)揮其優(yōu)勢(shì)所在。


          • 那些任務(wù)強(qiáng)制等待或者阻塞的原因,大多是因?yàn)閭鬏敂?shù)據(jù)或訪問(wèn)外部設(shè)備等帶來(lái)的I/O操作或網(wǎng)絡(luò)請(qǐng)求。這里的Waiting就是請(qǐng)求開(kāi)始到響應(yīng)之間需要等待的時(shí)間,就阻塞了。

          • 一個(gè)典型的CPU處理數(shù)據(jù)的能力是硬盤(pán)或網(wǎng)絡(luò)請(qǐng)求的好幾個(gè)數(shù)量級(jí),因此一個(gè)需要大的I/O操作的同步程序,需要花費(fèi)大量的時(shí)間等待I/O操作或網(wǎng)絡(luò)將數(shù)據(jù)準(zhǔn)備好。這是因?yàn)檫@個(gè)原因,同步的程序就叫做阻塞的程序。

          [3] 操作系統(tǒng)模型中的進(jìn)程變化狀態(tài)

          阻塞和非阻塞

          • 阻塞與非阻塞的概念是針對(duì)IO狀態(tài)而言的,關(guān)注程序在等待 IO 調(diào)用返回這段時(shí)間的狀態(tài)。當(dāng)線程或進(jìn)程調(diào)用每一個(gè)函數(shù)的時(shí)候,如果需要等待I/O請(qǐng)求等待競(jìng)爭(zhēng)資源的時(shí)候,操作系統(tǒng)就緒將其阻塞起來(lái),避免浪費(fèi)更多的CPU資源。等待完成之后,將其轉(zhuǎn)換為就緒狀態(tài)繼續(xù)運(yùn)行。

          • 阻塞和非阻塞,以及同步和異步,完全是兩組概念且之間并沒(méi)有一個(gè)必然的聯(lián)系。也就是阻塞并不等于同步,非阻塞并不等于異步。




          2. IO 編程模型

          該編程模型是為了解決 I/O 比較慢而產(chǎn)生的,熟悉和理解該模型有利于我們自己編寫(xiě)異步非阻塞的代碼

          什么是 IO 模型

          • 當(dāng)I/O發(fā)生的時(shí)候就會(huì)涉及到對(duì)象和步驟的操作,我們這里以網(wǎng)絡(luò)I/O的read為例。它會(huì)涉及到兩個(gè)系統(tǒng)對(duì)象,一個(gè)是調(diào)用這個(gè)I/O操作的進(jìn)程或線程,另一個(gè)就是系統(tǒng)內(nèi)核。當(dāng)read操作發(fā)生時(shí),第一步會(huì)等待數(shù)據(jù)準(zhǔn)備(磁盤(pán)到內(nèi)核內(nèi)存),第二步會(huì)將數(shù)據(jù)從內(nèi)核拷貝到進(jìn)程中去(內(nèi)核內(nèi)存到進(jìn)程內(nèi)存)。

          • 而在Python編程中,第一階段是準(zhǔn)備數(shù)據(jù)階段,第二階段是返回計(jì)算結(jié)果階段。所以對(duì)于下面的模型說(shuō)明,需要我們自行對(duì)照理解。



          [1] 阻塞型 I/O 模型

          • 在I/O執(zhí)行的兩個(gè)階段中,應(yīng)用進(jìn)程都被阻塞狀態(tài),即準(zhǔn)備數(shù)據(jù)階段和返回計(jì)算結(jié)果都是處于等待的狀態(tài)中,消耗CPU性能。


          [2] 非阻塞 I/O 模型

          • 非阻塞型I/O中,應(yīng)用進(jìn)程需要不斷的主動(dòng)詢問(wèn)第一階段是否已經(jīng)完成了。應(yīng)用進(jìn)程在第一階段雖然不用一直阻塞,但是需要不斷的主動(dòng)詢問(wèn),基本屬于忙等狀態(tài),所以非阻塞型不一定比阻塞型就好。


          [3] 復(fù)用 I/O 模型

          • 在應(yīng)用進(jìn)程和內(nèi)核中間加一個(gè)代理,所有的請(qǐng)求都交給代理去處理,自己只需要等待結(jié)果就可以了。這個(gè)代理就是我們熟知的select和poll模型,兩者基本沒(méi)有區(qū)別。

          • 即使有了代理,依然還是阻塞的,因?yàn)橛锌赡軙?huì)阻塞在代理上,如select和poll。有了代理最大的好處是,即使阻塞了但代理還可以接受其他用戶請(qǐng)求。對(duì)性能沒(méi)有太大的提升,因?yàn)檫€是阻塞的,只是能夠處理其他請(qǐng)求而已。


          [4] 信號(hào)驅(qū)動(dòng)式 IO 模型

          • 在第一階段中,應(yīng)用進(jìn)程只需要通知內(nèi)核加載磁盤(pán)內(nèi)容,加載完成之后,內(nèi)核會(huì)通知已經(jīng)完成。應(yīng)用進(jìn)程還可以響應(yīng)其他請(qǐng)求,而不怕阻塞在代理上。

          • 可以理解為,一個(gè)進(jìn)程可以響應(yīng)多個(gè)請(qǐng)求,這里的性能不一定非常好,因?yàn)镮/O的第二階段還是處于阻塞的狀態(tài)。


          [5] 異步 IO 模型

          • 五種I/O模型里面,除了異步IO模型以外,都是同步的。所以,再次驗(yàn)證了阻塞并不等于同步,非阻塞并不等于異步。

          • 異步I/O模型,應(yīng)用進(jìn)程只需要通知內(nèi)核,內(nèi)核默默的完成第一和第二階段,完成之后通知進(jìn)程已經(jīng)完成了。真正的實(shí)現(xiàn)了不阻塞、不等待的模型。一個(gè)進(jìn)程可以響應(yīng)多個(gè)請(qǐng)求,性能極大地提升。

          • 水平觸發(fā):完成之后通知應(yīng)用進(jìn)程,如果沒(méi)有收到,會(huì)一直發(fā)送,直到處理位置,非常消耗資源。

          • 邊緣觸發(fā):完成之后通知應(yīng)用進(jìn)程,只通知一次,如果沒(méi)有處理則存放起來(lái)并告訴其位置,比較好的方式。



          3. 事件驅(qū)動(dòng)

          這些使用場(chǎng)景大多出現(xiàn)在C/S模型中網(wǎng)絡(luò)比較繁忙的服務(wù)器端

          異步模型的使用場(chǎng)景

          • 有大量的任務(wù),因此在一個(gè)時(shí)刻至少有一個(gè)任務(wù)要運(yùn)行

          • 任務(wù)執(zhí)行大量的I/O操作,同步模型會(huì)讓任務(wù)阻塞而浪費(fèi)CPU時(shí)間

          • 任務(wù)之間相互獨(dú)立,以至于任務(wù)內(nèi)部的交互很少

          事件驅(qū)動(dòng)模型就是通過(guò)事件來(lái)觸發(fā)對(duì)應(yīng)的操作

          事件驅(qū)動(dòng)模型

          • 事件驅(qū)動(dòng)模型主要應(yīng)用在圖形用戶界面、網(wǎng)絡(luò)服務(wù)和Web前端上。舉個(gè)編寫(xiě)圖形用戶界面程序的例子,要給界面上每一個(gè)按鈕都添加監(jiān)聽(tīng)函數(shù),而該函數(shù)則只有在相應(yīng)的按鈕被用戶點(diǎn)擊的事件發(fā)生時(shí)才會(huì)執(zhí)行,開(kāi)發(fā)者并不需要事先確定事件何時(shí)發(fā)生,只需要編寫(xiě)事件的響應(yīng)函數(shù)即可。監(jiān)聽(tīng)函數(shù)或者響應(yīng)函數(shù)就是所謂的事件處理?(event handler),類似的事件還有鼠標(biāo)移動(dòng)、按下、松開(kāi)、雙擊等等,這就是事件驅(qū)動(dòng)。

          • 事件驅(qū)動(dòng)的程序一般都有一個(gè)主循環(huán)(main loop)或稱事件循環(huán)(event loop),該循環(huán)不停地做兩件事:事件監(jiān)測(cè)和事件處理。首先要監(jiān)測(cè)是否發(fā)生了事件,如果有事件發(fā)生則調(diào)用相應(yīng)的事件處理程序,處理完畢再繼續(xù)監(jiān)測(cè)新事件。事件循環(huán)只是在一個(gè)進(jìn)程中運(yùn)行的單個(gè)線程

          • 在Python2標(biāo)志性的異步框架就是Tornado(也存在事件循環(huán))、Twisted(基于事件驅(qū)動(dòng)的網(wǎng)絡(luò)引擎框架)、Gevent(使用的是協(xié)程),它們的共同特點(diǎn)就是異步非阻塞,而在Python3.6標(biāo)準(zhǔn)庫(kù)中已經(jīng)自帶了asyncio。


          原文鏈接:https://www.escapelife.site/posts/ab1905ae.html

          文章轉(zhuǎn)載:Python編程學(xué)習(xí)圈
          (版權(quán)歸原作者所有,侵刪)

          點(diǎn)擊下方“閱讀原文”查看更多

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人妻无码免费视频 | 无码成人在线观看 | a一级欧美| 一级欧美日韩 | 国产精品美女久久久久久 |