先理解一下用戶空間和內核空間,系統爲了保護內核數據,會將尋址空間分爲用戶空間和內核空間,32位機器爲例,高1G字節做爲內核空間,低3G字節做爲用戶空間。當用戶程序讀取數據的時候,會經歷兩個過程:磁盤到內核空間(這塊消耗性能,下面簡稱內核數據準備),內核空間拷貝到用戶空間(下面簡稱用戶空間拷貝)。linux
內核數據準備這部分是由DMA芯片實現的,而用戶空間拷貝的實現則是由CPU實現的,後者很是快,能到1G以上,因此,所謂的阻塞基本是內核數據準備的過程,這塊消耗時間。爲啥呢?簡單的理解就是,磁盤和內核緩存的速度自己就存在很大的差距。windows
同步異步是基於任務序列可靠性的角度區分,當一個任務依賴另一個任務時,緩存
同步就是,只有等被依賴的任務完成以後,依賴任務纔算完成,是一種可靠任務序列。好比打電話。併發
異步就是,只是通知被依賴任務去作某件事情,由被依賴任務完成以後通知依賴任務,可是不能保證被依賴任務完成,是一個不可靠任務序列。好比發短信。異步
同步異步的選擇其實就是可靠性和性能以前的取捨和平衡。函數
而阻塞非阻塞則是從CPU消耗的角度去區分。性能
阻塞就是讓CPU閒置,等IO等慢操做完成以後再繼續。spa
非阻塞則是在等IO等慢操做的完成的同時,CPU去作一些其餘事情。存在上下文切換。操作系統
阻塞非阻塞的選擇就是在CPU利用率和系統切換成本之間的平衡。3d
上面四者兩兩組合狀況以下
當咱們進行IO操做的時候,若是被調用者將任務所有執行完返回,稱爲同步/阻塞 IO。
若是被調用者,無論沒有操做成功,直接返回一個結果碼,可是再也不主動通知後續結果,稱爲非阻塞IO;這種狀況下須要重複調用查詢狀態。
若是被調用者,無論有沒有操做成功,直接返回個結果碼,等到所有操做完成以後再發一個信號通知調用者,稱爲異步IO。
家裏有個專門幫忙作飯的阿姨,有一天我想喝水了,我讓阿姨幫忙燒一壺水。
我看着她去燒水,灌水,給我倒水,期間沒有作其餘任何事情,這就是同步。
我想着也不用一直等,能夠先看會兒電視,我就隔一下子來看一次,隔一下子來看一次,這叫非阻塞。
再想一想,這也煩,我索性跟阿姨說,好了叫我一聲,而後就去看電視去了,這叫異步。
IO多路複用是基於阻塞IO的衍生,主要是爲了提升內核空間數據準備這一塊的功能複用,即阻塞的同時監聽多個端口,有一個端口有數據就進行處理,提升性能。
信號驅動IO則是在內核空間數據準備這一塊採用異步,在用戶空間拷貝這一塊採用同步。
同步阻塞IO(Java IO)
l 用戶進程發起一個IO操做以後,必須等待IO操做完成。
同步非阻塞IO(Java NIO)
l 用戶發起一個IO操做以後,返回作其餘事情,時不時的去詢問IO是否就緒。
多路複用IO
l 用戶發起一個IO操做以後,返回,等內核完成IO以後通知應用程序,這裏的阻塞是指返回以後並無作其餘是,而是一併監聽多個文件句柄,在select函數中,提升系統併發性。
異步非阻塞IO(Java NIO2)
l 用戶發起一個IO操做以後,返回,等待 內核數據準備 和 用戶空間拷貝都完成以後通知應用進程,中有實現。
NIO中的概念
Buffer:高效的數據容器,除了布爾類型,全部數據類型都有相應的Buffer實現。
Channel:做用相似Linux系統中的文件描述符,是用於支持抽象批量IO的一種抽象。相對於File/Socket:Channel是更加接近操做系統底層的一種抽象。
Selector:是NIO中多路複用的基礎,能夠同時檢測註冊在Selector上的多個Channel,進而對準備好的任一Channel進行處理。(這部分在linux中依賴epoll,windows上依賴iocp)
Charset,提供了字符編解碼器,能夠實現字符到ByteBuffer的轉換。
內存映射:能夠將內核空間地址和用戶空間地址映射到同一物理地址
零拷貝技術:數據只在內核空間流轉,沒有通過用戶空間。