【死磕NIO】— 阻塞、非阻塞、同步、異步,傻傻分不清楚
萬(wàn)事從最基本的開始。
要想完全掌握 NIO,并不是掌握上面文章(【死磕NIO】— NIO基礎(chǔ)詳解)中的三大組件就可以了,我們還需要掌握一些基本概念,如什么是 IO,5 種IO模型的區(qū)別,什么是阻塞&非阻塞等等,只有掌握了這些基本概念,我們對(duì)NIO才能理解得更加得心應(yīng)手。
這篇文章我們就從阻塞&非阻塞,同步&異步說起。
同步與異步
什么是同步與異步呢?百度百科是這樣定義的:
同步指兩個(gè)或兩個(gè)以上隨時(shí)間變化的量在變化過程中保持一定的相對(duì)關(guān)系。
異步與同步相對(duì)(這解釋讓我無(wú)言相對(duì))
所以,我們需要明確的是**同步與異步針對(duì)的是兩個(gè)或者兩個(gè)以上的事物**。
對(duì)于同步而言,一個(gè)任務(wù)(調(diào)用者)的完成需要依賴另一個(gè)人任務(wù)(被調(diào)用者)的完成,只有等待被依賴的任務(wù)完成,依賴的任務(wù)才會(huì)繼續(xù)進(jìn)行,兩者步調(diào)保持一致。
異步呢?任務(wù)與它依賴的任務(wù)沒有必然的聯(lián)系,它不需要等待它依賴的任務(wù)完成,它只需要向依賴任務(wù)發(fā)起調(diào)用即可,告訴它你可以干活了,至于你啥時(shí)候干完跟我沒關(guān)系。
所以說,同步和異步的本質(zhì)區(qū)別就在于調(diào)用者與被調(diào)用者之間結(jié)果消息通知機(jī)制的不同。
同步:調(diào)用者需要一直 主動(dòng)等待被調(diào)用者的結(jié)果。異步:調(diào)用者調(diào)用被調(diào)用者后,調(diào)用者不會(huì)立刻得到結(jié)果,在調(diào)用者發(fā)起調(diào)用后,被調(diào)用者通過狀態(tài)、通知或通過回調(diào)函數(shù),讓調(diào)用者知道結(jié)果
所以,同步和異步一個(gè)是主動(dòng)等待結(jié)果,一個(gè)是被動(dòng)知道結(jié)果。
舉一個(gè)簡(jiǎn)單的例子:買奶茶,我們有兩種方式拿到我們買的奶茶
選擇排隊(duì)等待。這種方式就是同步等待消息通知了,我們需要一直在吧臺(tái)面前等著我們的奶茶 掃碼。這種方式,你可以不停地看手機(jī)排號(hào)是否到你了(狀態(tài)),也可以在那里玩手機(jī)等著服務(wù)員喊 88 號(hào),奶茶好了(通知)。
上面提到異步調(diào)用可以通過狀態(tài)、通知或者回調(diào)函數(shù)來(lái)告知調(diào)用者。
狀態(tài):調(diào)用者需要每隔一段向被調(diào)用者發(fā)起一個(gè)狀態(tài)查詢請(qǐng)求。這種方式效率較為低下。一般我們?cè)谡{(diào)用支付接口的時(shí)候,如果服務(wù)方告知支付狀態(tài)未知,則我們需要每隔一段時(shí)間去查詢?cè)摴P訂單的支付狀態(tài)。雖然效率較為低下,但是靠譜。 通知:這種方式,調(diào)用者不需要做額外的工作,他只需要等被調(diào)用者把結(jié)果告訴調(diào)用者即可。但是這種方式也有點(diǎn)不是那么靠譜,它到底啥時(shí)候調(diào)用,如果不調(diào)用怎么辦呢?這些都是我們需要考慮的問題。 回調(diào)函數(shù):和通知機(jī)制差不多。
阻塞與非阻塞
上面解釋了什么是同步與異步,那什么是阻塞與非阻塞呢?
所謂阻塞,就是有障礙而不能通行,無(wú)法暢通。
所以,阻塞就是調(diào)用結(jié)果返回之前,該線程會(huì)被一直掛起,一直等待結(jié)果,不能繼續(xù),函數(shù)只有在得到結(jié)果之后才會(huì)返回。
可能有小伙伴會(huì)將阻塞與同步等同起來(lái),因?yàn)樗麄兌际且驗(yàn)榈却龍?zhí)行結(jié)果而停滯不前,其實(shí)兩者還是有區(qū)別的:
同步,針對(duì)的是兩個(gè)進(jìn)程,一個(gè)進(jìn)程(調(diào)用者)因?yàn)榈却硪粋€(gè)進(jìn)程(被調(diào)用者)的執(zhí)行結(jié)果而停滯不前。而阻塞則是針對(duì)一個(gè),它是因?yàn)樽约罕旧硪虻却?dāng)前線程中某個(gè)執(zhí)行結(jié)果而停滯不前的。 對(duì)于同步來(lái)說,當(dāng)前線程還是處于激活狀態(tài),只是從邏輯(感官)來(lái)說它是停滯不前的,當(dāng)前線程可能還在處理其他事情。而阻塞則不同,當(dāng)前線程是被掛起了,直接讓出了 CPU。
非阻塞則與阻塞概念相對(duì),指在不能立即得到執(zhí)行結(jié)果之前,該函數(shù)不會(huì)阻礙當(dāng)前線程執(zhí)行,而是會(huì)立即返回。
還是上面那個(gè)買奶茶的例子,不論是排隊(duì)在那里等奶茶還是掃碼在哪里等奶茶,只要在等奶茶的過程中你沒有做其他事情都是阻塞。如果你在等的過程跟你女朋友聊天(假如你有女朋友的話)或者在玩手機(jī),那么就是非阻塞,因?yàn)闆]有因等待奶茶這件事一直耗著,而是一邊等一邊干其他的事情。
同步&異步、阻塞&非阻塞
同步&異步與阻塞&非阻塞兩兩組合,分別為同步阻塞,同步非阻塞,異步阻塞,異步非阻塞。以上面等奶茶的例子為例。
同步阻塞
你在排隊(duì)等奶茶的過程中,什么事情都不能做,只能干等著。就問你無(wú)聊不無(wú)聊,尷尬不尷尬。效率最為低下。
同步非阻塞
你在排隊(duì)等奶茶的過程中,可以干其他事情,比如刷抖音,玩一把王者榮耀,但是你需要不斷地看奶茶是否已經(jīng)到你,你勢(shì)必會(huì)分心導(dǎo)致輸?shù)敉跽邩s耀,成為一個(gè)坑貨。注意排隊(duì)等奶茶,玩王者榮耀是兩件事情,你需要兩件事情來(lái)回不斷地切換,效率也不見得高到哪里去。
異步阻塞
你掃碼拿號(hào)后,你不用在那里排隊(duì)干等,你只需要等候服務(wù)員告訴你奶茶做好了去拿就可以了,但是在這個(gè)等的過程中,你啥事都不能干,只能干等著。很顯然你已經(jīng)被阻塞在這個(gè)等待服務(wù)員告訴你奶茶做好了的事情(消息通知)上面了。我們要注意是,并不是說異步就不能阻塞了,異步也是可以阻塞的,只不過它不是在處理消息時(shí)阻塞,而是在等待消息通知時(shí)被阻塞了。
異步非阻塞
你掃碼拿號(hào)后,直接去邊上玩王者榮耀了,中途你專心玩的王者榮耀,不需要分心去關(guān)注你的奶茶是否做好了,你只需要在那里等服務(wù)員告訴你奶茶做好了(消息通知)去拿就可以了。效率最高。
參考資料
https://www.cnblogs.com/xiaoQLu/p/10670333.html https://zhuanlan.zhihu.com/p/385202919
『chenssy』,江湖人稱大明哥,專注于【死磕 Java】系列文章創(chuàng)作。
【死磕 Java】系列是大明哥精心打造Java 進(jìn)階類系列文章,深入分析 Java 技術(shù)核心原理,從源碼層次闡述 Java 相關(guān)技術(shù)。目前系列包括:
【死磕 Java 并發(fā)】:https://www.cmsblogs.com/category/1391296887813967872:(已完成) 2.【死磕 Spring 之 IOC】:https://www.cmsblogs.com/category/1391374860344758272:(已完成)
3.【死磕 Redis】:https://www.cmsblogs.com/category/1391389927996002304:(已完成)
4.【死磕 Java 基礎(chǔ)】:https://www.cmsblogs.com/category/1411518540095295488
5.【死磕 NIO】:https://www.cmsblogs.com/article/1435620402348036096
