<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>

          這次,讓我們捋清:同步、異步、阻塞、非阻塞

          共 2376字,需瀏覽 5分鐘

           ·

          2022-02-10 14:09

          大家好,我是yes。

          繼上一篇說(shuō)透I/O模型后,我們來(lái)談?wù)劸W(wǎng)絡(luò) I/O 經(jīng)常會(huì)伴隨的幾個(gè)容易令人混淆的概念:同步、異步、阻塞、非阻塞的區(qū)別。

          這篇寫(xiě)完之后鋪墊就差不多了,之后就正式開(kāi)始 Netty 深度剖析了,敬請(qǐng)期待,嘻嘻。

          話不多說(shuō),發(fā)車!

          同步&異步

          同步和異步指的是:當(dāng)前線程是否需要等待方法調(diào)用執(zhí)行完畢。

          比如你調(diào)用一個(gè)搬運(yùn)一百塊石頭的方法:

          • 同步指的是調(diào)用這個(gè)方法,你的線程需要等待這一百塊石頭搬完,然后得到搬完了的結(jié)果,接著再繼續(xù)執(zhí)行剩下的代碼邏輯。
          //同步方式

          result?=?搬一百塊石頭();
          //需等待搬完的結(jié)果,才能執(zhí)行下面的邏輯
          if(result)?{
          石頭搬完了發(fā)工資();
          }
          計(jì)算下一次搬石頭的任務(wù)();
          • 異步指的是調(diào)用這個(gè)方法,立馬就直接返回,不必等候這一百塊石頭還未搬完,可以立馬執(zhí)行后面的代碼邏輯,然后利用回調(diào)或者事件通知的方式得到石頭已經(jīng)搬完的結(jié)果。
          //異步方式

          搬一百塊石頭({
          ????//回調(diào)
          ?石頭搬完了發(fā)工資();
          });
          //不必等待石頭搬完,立馬執(zhí)行下面的邏輯
          計(jì)算下一次搬石頭的任務(wù)();

          可以很直觀的看出,同步和異步就是調(diào)用方式的不同,這使得我們的編碼方式也有所不同。

          在異步調(diào)用下的代碼邏輯相對(duì)而言不太直觀,需要借助回調(diào)或事件通知,這在復(fù)雜邏輯下對(duì)編碼能力的要求較高。而同步調(diào)用就是直來(lái)直去,等待執(zhí)行完畢然后拿到結(jié)果緊接著執(zhí)行下面的邏輯,對(duì)編碼能力的要求較低,也更不容易出錯(cuò)。

          所以你會(huì)發(fā)現(xiàn)有很多方法它是異步調(diào)用的方式,但是最終的使用還是異步轉(zhuǎn)同步。

          比如你向線程池提交一個(gè)任務(wù),得到一個(gè) future,此時(shí)是異步的,然后你在緊接著在代碼里調(diào)用 future.get(),那就變成等待這個(gè)任務(wù)執(zhí)行完成,這就是所謂的異步轉(zhuǎn)同步,像 Dubbo RPC 調(diào)用同步得到返回結(jié)果就是這樣實(shí)現(xiàn)的。

          阻塞&非阻塞

          阻塞和非阻塞指的是:當(dāng)前接口數(shù)據(jù)還未準(zhǔn)備就緒時(shí),線程是否被阻塞掛起。

          何為阻塞掛起?就是當(dāng)前線程還處于 CPU 時(shí)間片當(dāng)中,調(diào)用了阻塞的方法,由于數(shù)據(jù)未準(zhǔn)備就緒,則時(shí)間片還未到就讓出 CPU。

          所以阻塞和同步看起來(lái)都是等,但是本質(zhì)上它們不一樣,同步的時(shí)候可沒(méi)有讓出 CPU。

          而非阻塞就是當(dāng)前接口數(shù)據(jù)還未準(zhǔn)備就緒時(shí),線程不會(huì)被阻塞掛起,可以不斷輪詢請(qǐng)求接口,看看數(shù)據(jù)是否已經(jīng)準(zhǔn)備就緒。

          至此我們可以得到一個(gè)結(jié)論:

          • 同步&異步指:當(dāng)數(shù)據(jù)還未處理完成時(shí),代碼的邏輯處理方式不同。
          • 阻塞&非阻塞指:當(dāng)數(shù)據(jù)還未處理完成時(shí)(未就緒),線程的狀態(tài)。

          所以同步&異步其實(shí)是處于框架這種高層次維度來(lái)看待的,而阻塞&非阻塞往往針對(duì)底層的系統(tǒng)調(diào)用方面來(lái)抉擇,也就是說(shuō)兩者是從不同維度來(lái)考慮的。

          再結(jié)合 I/O 來(lái)看

          前提:程序和硬件之間隔了個(gè)操作系統(tǒng),而為了安全考慮,Linux 系統(tǒng)分了:用戶態(tài)和內(nèi)核態(tài)

          在這個(gè)前提下,我們?cè)倜鞔_ I/O 操作有兩個(gè)步驟:

          1. 發(fā)起 I/O 請(qǐng)求
          2. 實(shí)際 I/O 讀寫(xiě),即數(shù)據(jù)從內(nèi)核緩存拷貝到用戶空間

          阻塞 I/O 和非阻塞 I/O。按照上文,其實(shí)指的就是用戶線程是否被阻塞,這里指代的步驟1(發(fā)起I/O請(qǐng)求)。

          • 阻塞 I/O,指用戶線程發(fā)起 I/O 請(qǐng)求的時(shí)候,如果數(shù)據(jù)還未準(zhǔn)備就緒(例如暫無(wú)網(wǎng)絡(luò)數(shù)據(jù)接收),就會(huì)阻塞當(dāng)前線程,讓出 CPU。
          • 非阻塞 I/O,指用戶線程發(fā)起 I/O 請(qǐng)求的時(shí)候,如果數(shù)據(jù)還未準(zhǔn)備就緒(例如暫無(wú)網(wǎng)絡(luò)數(shù)據(jù)接收),也不會(huì)阻塞當(dāng)前線程,可以繼續(xù)執(zhí)行后續(xù)的任務(wù)。

          可以發(fā)現(xiàn),這里的阻塞和非阻塞其實(shí)是指用戶線程是否會(huì)被阻塞。

          同步 I/O 和異步 I/O。按照上文,我們可以得知這就是根據(jù) I/O 響應(yīng)方式不同而劃分的。

          • 同步 I/O,指用戶線程發(fā)起 I/O 請(qǐng)求的時(shí)候,數(shù)據(jù)是有的,那么將進(jìn)行步驟2(實(shí)際 I/O 讀寫(xiě),即數(shù)據(jù)從內(nèi)核緩存拷貝到用戶空間),這個(gè)過(guò)程用戶線程是要等待著拷貝完成。
          • 異步 I/O,指用戶線程發(fā)起 I/O 請(qǐng)求的時(shí)候,數(shù)據(jù)是有的,那么將進(jìn)行步驟2(實(shí)際 I/O 讀寫(xiě),即數(shù)據(jù)從內(nèi)核緩存拷貝到用戶空間),拷貝的過(guò)程中不需要用戶線程等待,用戶線程可以去執(zhí)行其它邏輯,等內(nèi)核將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間后,用戶線程會(huì)得到一個(gè)“通知”。

          再仔細(xì)思考下,在 I/O 場(chǎng)景下同步和異步說(shuō)的其實(shí)是內(nèi)核的實(shí)現(xiàn),因?yàn)榭截惖膱?zhí)行者是內(nèi)核,一種是同步將數(shù)據(jù)拷貝到用戶空間,用戶線程是需要等著的。一個(gè)是通過(guò)異步的方式,用戶線程不用等,在拷貝完之后,內(nèi)核會(huì)調(diào)用指定的回調(diào)函數(shù)。

          如果不理解上面,就只需記住:

          • 同步I/O:指的是用戶線程會(huì)需要等待步驟 2 執(zhí)行完畢。
          • 異步I/O:指的是用戶線程不需要等待步驟 2 執(zhí)行。

          好了,如果以上的概念你都已經(jīng)理解了的話,那么平日里我們所說(shuō)的同步阻塞I/O,同步非阻塞I/O等其實(shí)就是把上面的兩個(gè)步驟合起來(lái)看,應(yīng)該不難理解。

          我再簡(jiǎn)單的總結(jié)一下,關(guān)于 I/O 的阻塞、非阻塞、同步、異步:

          • 阻塞和非阻塞指的是發(fā)起 I/O 請(qǐng)求后,用戶線程狀態(tài)的不同,阻塞I/O在數(shù)據(jù)未準(zhǔn)備就緒的時(shí)候會(huì)阻塞當(dāng)前用戶線程,而非阻塞 I/O 會(huì)立馬返回一個(gè)錯(cuò)誤,不會(huì)阻塞當(dāng)前用戶線程。
          • 同步和異步是指,內(nèi)核的 I/O 拷貝實(shí)現(xiàn),當(dāng)數(shù)據(jù)準(zhǔn)備就緒后,需要將內(nèi)核空間的數(shù)據(jù)拷貝至用戶空間,如果是同步 I/O 那么用戶線程會(huì)等待拷貝的完成,而異步 I/O則這個(gè)拷貝過(guò)程用戶線程該干嘛可以去干嗎,當(dāng)內(nèi)核拷貝完畢之后會(huì)“通知”用戶線程。

          最后

          要注意,不同場(chǎng)景下同一個(gè)名詞意義可能不同。我這篇關(guān)于同步、異步、阻塞、非阻塞這幾個(gè)概念是基于 I/O 場(chǎng)景下講的。

          個(gè)人能力有限,不知道有沒(méi)有講清楚,如有疑問(wèn)可以留言區(qū)哈。

          瀏覽 38
          點(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>
                  三级久久久 | 色之综合天天综合色天天素质 | 狠操在线| 超碰在线免费大屁股导航 | 狼狠操|