在高性能的I/O體系設計中,有幾個概念經常會使咱們感到疑惑不解。具體以下:編程
1 什麼是同步?服務器
2 什麼是異步?架構
3 什麼是阻塞?併發
4 什麼是非阻塞?異步
5 什麼是同步阻塞?函數
6 什麼是同步非阻塞?性能
7 什麼是異步阻塞?線程
8 什麼是異步非阻塞?設計
先來舉個現實生活中的例子:進程
若是你想吃一份宮保雞丁蓋飯,
同步阻塞:你到飯館點餐,而後在那兒等着,還要一邊喊:好了沒啊!
同步非阻塞:在飯館點完餐,就去遛狗了。不過遛一下子,就回飯館喊一聲:好了沒啊!
異步阻塞:遛狗的時候,接到飯館電話,說飯作好了,讓您親自去拿。
異步非阻塞:飯館打電話說,咱們知道您的位置,一下子給你送過來,安心遛狗就能夠了。
在弄清楚以上幾個問題以前,咱們首先得明白什麼是同步、異步、阻塞、非阻塞,只有這幾個概念單個理解清楚了,而後再組合起來理解,就比較容易了。
1 同步和異步是針對 應用程序和內核的交互 而言的。
2 阻塞和非阻塞是針對於進程在訪問數據時,根據I/O操做的就緒狀態來採起的不一樣方式,說白了是一種讀取或寫入操做函數的實現方式。阻塞方式下,讀取或寫入函數將一直等待,而非阻塞方式下,讀取或寫入函數會當即返回一個狀態值。
以上描述能夠總結爲一句簡短的話:同步和異步是目的,阻塞和非阻塞是實現方式。
1 同步:指的是用戶進程觸發I/O操做並等待或輪詢地去查看I/O操做是否就緒。本身上街買衣服,本身親自幹這件事,別的事幹不了。
2 異步:異步是指用戶進程觸發I/O操做之後便開始作本身的事情,而當I/O操做完成的時候會獲得「I/O完畢」的通知(異步的特色就是通知)。告訴朋友本身合適衣服的尺寸、顏色、款式,委託朋友去買,而後本身能夠去幹別的事(使用異步I/O時,Java將I/O讀寫委託給OS處理,須要將數據緩衝區地址和大小傳給OS)。
3 阻塞:所謂阻塞方式的意思是指,當試圖對該文件描述符進行讀寫時,若是當時沒有東西可讀,或暫時不可寫,程序就進入等待狀態,直到有東西可讀或可寫爲止。去地鐵站充值,發現這個時候充值員不在(可能上廁所去了),而後咱們就在原地等待,一直等到充值員回來爲止。
4 非阻塞:非阻塞狀態下,若是沒有東西可讀,或不可寫,讀寫函數立刻返回,而不會等待。在銀行裏辦業務時,領取一張小票,以後咱們能夠玩手機,或與別人聊聊天,當輪到咱們時,銀行的喇叭會通知,這時候咱們就能夠去辦業務了。
一個I/O操做其實分紅了兩個步驟:發起I/O請求和實際的I/O操做。
同步I/O和異步I/O的區別就在於第二個步驟是否阻塞,若是實際的I/O讀寫阻塞請求進程,那麼就是同步I/O。
阻塞I/O和非阻塞I/O的區別在於第一步,發起I/O請求是否會被阻塞,若是阻塞直到I/O完成,那麼就是傳統的阻塞I/O,若是不阻塞,那麼就是非阻塞
I/O。
同步和異步是針對應用程序和內核的交互而言的,同步指的是用戶進程觸發I/O操做並等待或輪詢地去查看I/O操做是否就緒,而異步是指用戶進程觸發I/O操做之後便開始作本身的事情,而當I/O操做完成的時候會獲得I/O完畢的通知。
阻塞和非阻塞是針對於進程在訪問數據時,根據I/O操做的就緒狀態來採起的不一樣方式,說白了是讀取或寫入操做函數的一種實現方式,阻塞方式下讀寫函數一直等待,而非阻塞方式下,讀寫函數會當即返回一個狀態值。
因此,I/O操做能夠分爲3類:同步阻塞(即早期的BIO操做)、同步非阻塞(NIO)、異步非阻塞(AIO)。
同步阻塞(BIO):
在此種方式下,用戶進程在發起一個I/O操做後,必須等待I/O操做的完成,只有當真正完成了I/O操做之後,用戶進程才能運行。JAVA傳統的I/O模式屬於此種方式。
同步非阻塞(NIO):
在此種方式下,用戶進程發起一個I/O操做之後即可返回作其餘事情,可是用戶進程須要時不時地詢問I/O操做是否就緒,這就要求用戶週期性地去詢問,從而引入沒必要要的CPU資源浪費。目前JAVA的NIO就屬於同步非阻塞I/O。
異步非阻塞(AIO):
此種方式下是指用戶進程發起一個I/O操做之後,不等待內核I/O操做的完成,內核完成I/O操做之後會通知用戶進程。
同步阻塞I/O(JAVA BIO):
同步並阻塞,服務器實現模式爲一個鏈接一個線程,即客戶端有鏈接請求時服務器就須要啓動一個線程進行處理,若是這個鏈接不作任何事情就會形成沒必要要的線程開銷。固然能夠經過線程池機制改善。
同步非阻塞I/O(JAVA NIO):同步非阻塞,服務器實現模式爲一個請求一個線程,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。用戶進程須要時不時地詢問I/O操做是否就緒,這就要求用戶進程週期性地去詢問。
異步阻塞I/O (JAVA NIO):
此種方式下是指應用發起一個I/O操做之後,不等待I/O操做的完成,內核完成I/O操做之後會通知應用程序,這其實就是同步和異步最關鍵的區別,同步必須等待或主動地去詢問I/O是否完成,那麼爲何說是阻塞的呢?由於此時是經過select系統調用來完成的,而select函數自己的實現方式是阻塞的,而採用select函數有個好處就是它能夠同時監聽多個文件句柄(若是從 UNP 的角度看,select屬於同步操做,由於select以後,進程還須要讀寫數據),從而提升系統的併發性!
異步非阻塞I/O(JAVA AIO(NIO.2)):
此種方式下,用戶進程之須要發起一個I/O操做而後當即返回,等I/O操做真正地完成之後,應用程序會獲得I/O操做完成的通知,此時用戶進程只須要對數據進行處理就行了,不須要進行實際的I/O讀寫操做,由於真正的I/O讀寫操做已經由內核完成了。
BIO、NIO、AIO的適用場景分析:
BIO方式適用於鏈接數目比較小且固定的架構,這種方式對服務器資源要求比較高,併發侷限於應用中,JDK1.4之前的惟一選擇,但程序直觀簡單易理解。
NIO方式適用於鏈接數目多且鏈接比較短(輕操做)的架構,好比聊天服務器,併發侷限於應用中,編程比較複雜,JDK1.4開始支持。
AIO方式適用於鏈接數目多且鏈接比較長(重操做)的架構,好比相冊服務器,充分調用OS參與併發操做,編程比較複雜,JDK7開始支持。