1. 程式人生 > >IO操作中的同步/非同步、阻塞/非阻塞的含義

IO操作中的同步/非同步、阻塞/非阻塞的含義

前言

學好IO是java程式設計師從初級到高階進階學習的必經之路,像Netty這種優秀網路框架是必須要學習的,說到Netty就離不開java的IO模型,我們知道BIO、NIO、AIO分別是同步阻塞IO、同步非阻塞IO、非同步非阻塞IO,那麼這裡說的同步和非同步、阻塞和非阻塞指的是什麼呢?

同步和非同步

在java IO世界所說的同步和非同步是一個針對使用者態和核心態的概念,使用者程式要想傳送資料要經過下面的步驟:

  1. 應用程式將要傳送的內容寫入使用者記憶體空間
  2. 應用程式向作業系統核心傳送系統呼叫
  3. 作業系統核心將使用者空間中的資料讀取到核心緩衝區
  4. 作業系統通知網絡卡讀取核心緩衝區的資料,此時CPU可以處理其他事
  5. 網絡卡從指定的核心空間讀取資料
  6. 網絡卡將資料轉換成二進位制形式,以位元流的形式傳輸

ps:下面說的使用者程序等同於應用程式,是同一個概念

在這個過程中才有同步非同步的概念:

同步和非同步是針對應用程式和核心的互動而言的.
同步指的是使用者程序觸發IO操作並等待或者輪詢的去檢視IO操作是否就緒
非同步是指使用者程序觸發IO操作以後便開始做自己的事情,而當IO操作已經完成的時候會得到IO完成的通知

同步和非同步的主要區別就是在使用者程式通過系統呼叫IO操作時是否需要等待或者輪詢,以便檢視作業系統是否完成了IO操作。

這裡的等待IO指的是資料從應用程式拷貝到核心空間(或從核心空間拷貝到使用者程式)的過程

。( 出於系統安全考慮,使用者執行緒是沒法直接讀取核心態記憶體的。)

阻塞和非阻塞

阻塞和非阻塞是針對於應用程式在訪問資料的時候,根據IO操作的就緒狀態來採取的不同方式,阻塞方式下讀取或者寫入過程將一直等待結果,而非阻塞方式下,讀取或者寫入過程會立即獲得一個返回值。

簡單來說就是阻塞情況下需要等待執行結果,非阻塞情況下立即獲得結果(不管最終操作成功還是失敗)。結合同步非同步過程理解,
阻塞:當用戶執行緒發起一個IO請求的時候,請求會到達核心,核心獲取到資料後,將資料從核心空間拷貝到使用者空間。期間,當核心未將資料準備好時,使用者執行緒一直處於阻塞狀態(使用者執行緒不會獲得反饋結果)


非阻塞:當用戶程式發起IO請求時,不用等到核心準備好資料才能返回,而是可以立刻返回(不論什麼狀態都獲得反饋結果),沒有被阻塞住。

java中的IO

  • 同步阻塞IO:在此種方式下,使用者程序在發起一個IO操作以後,必須等待IO操作的完成,只有當真正完成了IO操作以後,使用者程序才能執行。JAVA傳統的IO模型屬於此種方式!
  • 同步非阻塞IO:在此種方式下,使用者程序發起一個IO操作以後可立即返回做其它事情,但是使用者程序需要時不時的詢問IO操作是否就緒,這就要求使用者程序不停的去詢問,從而引入不必要的CPU資源浪費。其中目前JAVA的NIO就屬於同步非阻塞IO。
  • 非同步阻塞IO:此種方式下是指應用發起一個IO操作以後,不等待核心IO操作的完成,等核心完成IO操作以後會通知應用程式,這其實就是同步和非同步最關鍵的區別,同步必須等待或者主動的去詢問IO是否完成,那麼為什麼說是阻塞的呢?因為此時是通過select系統呼叫來完成的,而select函式本身的實現方式是阻塞的,而採用select函式有個好處就是它可以同時監聽多個檔案控制代碼,從而提高系統的併發性!(關於select函式不是本文重點)
  • 非同步非阻塞IO:在此種模式下,使用者程序只需要發起一個IO操作然後立即返回,等IO操作真正的完成以後,應用程式會得到IO操作完成的通知,此時使用者程序只需要對資料進行處理就好了,不需要進行實際的IO讀寫操作,因為真正的IO讀取或者寫入操作已經由核心完成了。