IO-同步、非同步、阻塞、非阻塞
1.同步與非同步
所謂同步就是一個任務的完成需要依賴另外一個任務時,只有等待被依賴的任務完成後,依賴的任務才有可能完成(當然我們可以根據事務回滾、資料恢復等使之成為一種可靠的任務序列:要成功都成功,要失敗都失敗,兩個任務的狀態保持一致);非同步不需要等待被依賴的任務完成,只是通知被依賴的任務要完成什麼工作,依賴的任務不需要等待其完成,即可立即執行,只要自己完成了整個任務就算完成了。至於被依賴的任務最終是否真正完成,依賴它的任務無法確定,所以它是不可靠的任務序列。我們可以用打電話和發簡訊來比喻同步與非同步操作。
2.阻塞與非阻塞
阻塞與非阻塞主要是從CPU的消耗上來說的,阻塞就是CPU停下來等待一個慢的操作完成以後,CPU才接著完成其它的事。非阻塞就是在這個慢的操作執行時CPU去幹其他別的事,等這個慢的操作完成時,CPU再接著完成後續的操作。雖然表面上看非阻塞的方式可明顯提高CPU的利用率,但是也帶來了另外一種後果,就是系統的執行緒切換增加。增加的CPU使用時間能不能補償系統切換成本需要好好評估。
3.兩種方式的組合
組合的方式有四種:分別是同步阻塞、同步非阻塞、非同步阻塞、非同步非阻塞。
-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
組合方式 | 效能分析
-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
同步阻塞 | 最常用的一種用法,使用也是最簡單的,但是I/O效能一般很差,CPU大部分處於空閒狀態
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 提升I/O效能的常用手段,就是講I/O的阻塞改成非阻塞方式,尤其在網路I/O是長連線同時傳輸資料也不是很多的情況下,提升效能非常有效
同步非阻塞 | 這種方式通常能提升I/O效能,但是會增加CPU消耗,要考慮增加的I/O效能能不能補償CPU的消耗,也就是系統的瓶頸實在I/O還是在CPU上。---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
非同步阻塞 | 這種方式在分散式資料庫中經常用到,例如,在一個分散式資料庫中寫一條記錄,通常會有一份同步阻塞的記錄,而還有兩至三份備份記錄
| 寫到其它機器上,這些備份記錄通常都採用非同步阻塞的方式寫I/O。
| 非同步阻塞對網路I/O能夠提升效率,尤其像上面這種同時寫多份相同資料的情況。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
非同步非阻塞 | 這種組合方式用起來比較複雜,只有在一些非常複雜的分散式,叢集之間的訊息同步機制一般採用這種I/O組合方式。
| 它適合同時要傳多份相同的資料到叢集中不同的機器,同時資料的傳輸量雖然不大但是卻非常頻繁,這種網路I/O用這個方式效能達到最高。
---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
舉例:
同步阻塞IO
你去一個銀行櫃檯存錢。首先,你會將存錢的單子填好,然後交給櫃員。這裡,你就好比是application,單子就是呼叫的 system call,櫃員就是kernel。提交好單子後,你就坐在櫃檯前等,相當於開始進行等待。櫃員辦好以後會給你一個回執,表示辦好了,這就是 response。然後你就可以拿著回執幹其它的事了。注意,這個時候,如果你辦完之後馬上去查賬,存的錢已經打到你的賬戶上了。後面你會發現, 這點很重要。
同步非阻塞IO
這次不是去銀行存錢,而是去銀行匯款。同樣的,你也需要填寫匯款單然後交給櫃員,櫃員進行一 些簡單的手續處理就能夠給你回執。但是,你拿到回執並不意味著錢已經打到了對方的賬上。事實上,一般匯款的週期大概是24個小時,如果你要以存錢的模式來 匯款的話,意味著你需要在銀行等24個小時,這顯然是不現實的。所以,同步非阻塞IO在實際生活中也是有它的意義的。
非同步阻塞IO
比如說一個銀行櫃檯,現在有10個人想存錢。按照現在銀行的做法,一個個排隊。第一個人先填存款單,然後提交, 然後櫃員處理,然後給回執,成功後再輪到下一個人。大家應該都在銀行排過對,這樣的流程是很痛苦的。如果按照非同步阻塞的機制,10個人都填好存款單,然後 都提交給櫃檯,提交完之後所有的10個人就在銀行大廳等待。這時候會專門有個人,他會了解存款單處理的情況,一旦有存款單處理完畢,他會將回執交給相應的 正在大廳等待的人,這個拿到回執的人就可以去幹其他的事情了。而前面提到的這個專人,就對應於select函式。
非同步非阻塞IO
比如銀行存錢。現在某銀行新開通了一項存錢業務。使用者之需要將存款單交給櫃檯,然後無需等待就可以離開了。櫃檯辦好以後會給使用者傳送一條簡訊,告知交易成功。這樣使用者不需要在櫃檯前進行長時間的等待,同時,也能夠得到確切的訊息知道交易完成。