Netty系列| 3張腦圖帶你看透IO

 

擊上方Java專欄」,選擇「置頂或者星標」
git


第一時間閱讀精彩文章!github


點擊這段文字獲取:5個能夠寫到簡歷的項目實戰視頻教程(含源碼)web


在學習Java I/O類庫時,容易混淆NIO、BIO、AIO這幾個概念,同時對於阻塞和非阻塞同步和異步的理解也較爲晦澀,這篇文章是對這幾個概念的一些區分以及我的的一些看法。面試


本篇是Netty系列的第一篇,因此咱們從瞭解這些概念出發,爲後續深刻Netty原理打下基礎數據庫


前言

各位,下面三張腦圖清楚的向你們展現IO安全


到這裏,咱們先來思考一個問題:咱們常常所說的「IO」的全稱究竟是什麼?
微信

可能不少人看到這個問題和我同樣一臉懵逼,IO的全稱實際上是:Input/Output的縮寫。網絡


下面就讓咱們來進入正題app

BIO,NIO,AIO對比

這裏只考慮兩個實體(客戶端、服務端),一個事件(客戶端向服務端請求數據)框架

同步、異步描述的是:客戶端在請求數據的過程當中,可否作其餘事情。

阻塞、非阻塞描述的是:客戶端與服務端是否從頭至尾始終都有一個持續鏈接,以致於佔用了通道,不讓其餘客戶端成功鏈接。

那麼BIO NIO AIO就能夠簡單的理解爲:

  • BIO(同步阻塞):客戶端在請求數據的過程當中,保持一個鏈接不能作其餘事情


  • NIO(同步非阻塞):客戶端在請求數據的過程當中,不用保持一個鏈接,不能作其餘事情。(不用保持一個鏈接,而是用許多個小鏈接,也就是輪詢)


  • AIO(異步非阻塞):客戶端在請求數據的過程當中,不用保持一個鏈接,能夠作其餘事情。(客戶端作其餘事情,數據來了等服務端來通知。)

是否是邏輯清楚了?結論下完了,接下來咱們說說同步與阻塞的理解。

同步和異步

常見的誤區

假設有一個展現用戶詳情的需求,分兩步,先調用一個HTTP接口拿到詳情數據,而後使用適合的視圖展現詳情數據。


若是網速很慢,代碼發起一個HTTP請求後,就卡住不動了,直到十幾秒後纔拿到HTTP響應,而後繼續往下執行。

這個時候你問別人,剛剛代碼發起的這個請求是否是一個同步請求,對方必定回答是。這是對的,它確實是。

但你要問它爲何是呢?對方必定是這樣回答的,「
由於發起請求後,代碼就卡住不動了,直到拿到響應後才能夠繼續往下執行」。

我相信不少人也都是這樣認爲的,其實這是不對的,是把因果關係搞反了:

不是由於代碼卡住不動了才叫同步請求,而是由於它是同步請求因此代碼才卡住不動了。

至於爲何能卡住不動,這是由操做系統和CPU決定的:

由於內核空間裏的對應函數會卡住不動,形成用戶空間發起的系統調用卡住不動,繼而使程序裏的用戶代碼卡住不動了。

所以卡住不動了只是同步請求的一個反作用,並不能用它來定義同步請求,那該如何定義呢?

同步

所謂同步,指的是協同步調。既然叫協同,因此至少要有2個以上的事物存在。協同的結果就是:

多個事物不能同時進行,必須一個一個的來,上一個事物結束後,下一個事物纔開始。

那當一個事物正在進行時,其它事物都在幹嗎呢?

嚴格來說這個並無要求,但通常都是處於一種「等待」的狀態,由於一般後面事物的正常進行都須要依賴前面事物的結果或前面事物正在使用的資源。

所以,能夠認爲,同步更但願關注的是從宏觀總體來看,多個事物是一種逐個逐個的串行化關係,絕對不會出現交叉的狀況。

因此,天然也不太會去關注某個瞬間某個具體事物是處於一個什麼狀態。

把這個理論應用的出神入化的非「排隊」莫屬。凡是在資源少需求多的場景下都會用到排隊。

好比排隊買火車票這件事:

其實售票大廳更在乎的是旅客一個一個的到窗口去買票,由於一次只能賣一張票。

即便你們一窩蜂的都圍上去,仍是一次只能賣一張票,何須呢?擠在一塊兒又不安全。

只是有些人素質太差,非要往上擠,售票大廳無可奈何,採用排隊這種形式來達到本身的目的,即一個一個的買票。

至於每一個旅客排隊時的狀態,是看手機呀仍是說話呀,根本不用去在乎。

除了這種因爲資源致使的同步外,還存在一種因爲邏輯上的前後順序致使的同步。

好比,先更新代碼,而後再編譯,接着再打包。這些操做因爲後一步要使用上一步的結果,因此只能按照這種順序一個一個的執行。

關於同步還需知道兩個小的點:

一是範圍,並不須要在全局範圍內都去同步,只須要在某些關鍵的點執行同步便可。

好比食堂只有一個賣飯窗口,確定是同步的,一我的買完,下一我的再買。但吃飯的時候也是一我的吃完,下一我的纔開始吃嗎?固然不是啦。

二是粒度,並非只有大粒度的事物纔有同步,小粒度的事物也有同步。


只不太小粒度的事物同步一般是自然支持的,而大粒度的事物同步每每須要手工處理。

好比兩個線程的同步就須要手工處理,但一個線程裏的兩個語句自然就是同步的。

異步

所謂異步,就是步調各異。既然是各異,那就是都不相同。因此結果就是:

多個事物能夠你進行你的、我進行個人,誰都不用管誰,全部的事物都在同時進行中。


一言以蔽之,同步就是多個事物不能同時開工,異步就是多個事物能夠同時開工。


注:必定要去體會「多個事物」,多個線程是多個事物,多個方法是多個事物,多個語句是多個事物,多個CPU指令是多個事物。等等等等。

阻塞和非阻塞

所謂阻塞,指的是阻礙堵塞。它的本意能夠理解爲因爲遇到了障礙而形成的動彈不得。


所謂非阻塞,天然是和阻塞相對,能夠理解爲因爲沒有遇到障礙而繼續暢通無阻。

對這兩個詞最好的詮釋就是,當今中國一大交通難題,堵車:

汽車能夠正常通行時,就是非阻塞。一旦堵上了,所有趴窩,一動不動,就是阻塞。


所以阻塞關注的是不能動,非阻塞關注的是能夠動。


不能動的結果就是隻能等待,能夠動的結果就是繼續前行。

所以和阻塞搭配的詞必定是等待,和非阻塞搭配的詞必定是進行。

回到程序裏,阻塞一樣意味着停下來等待,非阻塞代表能夠繼續向下執行。


從CPU角度來看就是這樣的:


阻塞與非阻塞主要是從 CPU 的消耗上來講的。

阻塞就是 CPU 停下來等待一個慢的操做完成 CPU 才接着完成其它的事。

非阻塞就是在這個慢的操做在執行時 CPU 去幹其它別的事,等這個慢的操做完成時,CPU 再接着完成後續的操做。雖然表面上看非阻塞的方式能夠明顯的提升 CPU 的利用率,可是也帶了另一種後果就是系統的線程切換增長。增長的 CPU 使用時間能不能補償系統的切換成本須要好好評估。

同步,異步和阻塞,非阻塞

所謂同步/異步,關注的是能不能同時開工

所謂阻塞/非阻塞,關注的是
能不能動

經過推理進行組合:

同步阻塞,不能同時開工,也不能動。只有一條小道,一次只能過一輛車,可悲的是還TMD的堵上了。

同步非阻塞,不能同時開工,但能夠動。只有一條小道,一次只能過一輛車,幸運的是能夠正常通行。

異步阻塞,能夠同時開工,但不能夠動。有多條路,每條路均可以跑車,可氣的是全都TMD的堵上了。

異步非阻塞,能夠工時開工,也能夠動。有多條路,每條路均可以跑車,很爽的是全均可以正常通行。


是否是很容易理解啊。
其實它們的關注點是不一樣的,只要搞明白了這點,組合起來也不是事兒。

回到程序裏,把它們和線程關聯起來:

同步阻塞,至關於一個線程在等待。

同步非阻塞,至關於一個線程在正常運行。

異步阻塞,至關於多個線程都在等待。

異步非阻塞,至關於多個線程都在正常運行。

性能分析

組合方式 性能分析
同步阻塞 最經常使用的一種用法,使用也是最簡單的,可是 I/O 性能通常不好,CPU 大部分在空閒狀態。
同步非阻塞 提高 I/O 性能的經常使用手段,就是將 I/O 的阻塞改爲非阻塞方式,尤爲在網絡 I/O 是長鏈接,同時傳輸數據也不是不少的狀況下,提高性能很是有效。這種方式一般能提高 I/O 性能,可是會增長CPU 消耗,要考慮增長的 I/O 性能能不能補償 CPU 的消耗,也就是系統的瓶頸是在 I/O 仍是在 CPU 上。
異步阻塞 這種方式在分佈式數據庫中常常用到,例如在往一個分佈式數據庫中寫一條記錄,一般會有一份是同步阻塞的記錄,而還有兩至三份是備份記錄會寫到其它機器上,這些備份記錄一般都是採用異步阻塞的方式寫 I/O。異步阻塞對網絡 I/O 可以提高效率,尤爲像上面這種同時寫多份相同數據的狀況。
異步非阻塞 這種組合方式用起來比較複雜,只有在一些很是複雜的分佈式狀況下使用,像集羣之間的消息同步機制通常用這種 I/O 組合方式。如 Cassandra 的 Gossip 通訊機制就是採用異步非阻塞的方式。它適合同時要傳多份相同的數據到集羣中不一樣的機器,同時數據的傳輸量雖然不大,可是卻很是頻繁。這種網絡 I/O 用這個方式性能能達到最高。


總結


本文狼王帶你瞭解了 IO的腦圖,探討了BIO,NIO,AIO,對比了同步、異步,阻塞、非阻塞以前的區別,帶你更好的再次瞭解這些知識,對後續Netty的學習頗有幫助的。

Netty系列的第一篇算是結束了,下篇將會着重講一下NIO,由於它是Netty的核心,後續我會不斷更新該系列文章,由淺至深,從簡到難,多方位多角度的帶你認識Netty這個網絡框架!但願大家是我最好的觀衆!

假如面試中你被問到這些,我相信你看了這篇必定能撥動面試官的心!



 
      
      
       
       
                
       
 
      
題外話: 推薦一個GitHub項目 ,這個 GitHub 整理了上百本經常使用技術PDF,絕大部分核心的技術書籍均可以在這裏找到,GitHub地址:https://github.com/gsjqwyl/awesome-ebook(電腦打開體驗更好),地址閱讀原文直達。麻煩打個給個Star,持續更新中...


---END---

文末福利



本文分享自微信公衆號 - Java專欄(finishbug)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索