[Java併發]IO多路複用

Duancf發表於2024-07-09

IO

IO多路複用

BIO

NIO

select

poll

epoll

水平觸發和邊沿觸發

  • 水平觸發只關心檔案描述符中是否還有沒完成處理的資料,如果有,不管怎樣epoll_wait,總是會被返回。簡單說——水平觸發代表了一種“狀態”。

  • 邊沿觸發只關心檔案描述符是否有的事件產生,如果有,則返回;如果返回過一次,不管程式是否處理了,只要沒有新的事件產生,epoll_wait不會再認為這個fd被“觸發”了。簡單說——邊沿觸發代表了一個“事件”。

    那麼邊沿觸發怎麼才能迫使新事件產生呢?一般需要反覆呼叫read/write這樣的IO介面,直到得到了EAGAIN錯誤碼,再去嘗試epoll_wait才有可能得到下次事件。

那麼為什麼需要邊沿觸發呢?

邊沿觸發把如何處理資料的控制權完全交給了開發者,提供了巨大的靈活性。比如,讀取一個http的請求,開發者可以決定只讀取http中的headers資料就停下來,然後根據業務邏輯判斷是否要繼續讀(比如需要呼叫另外一個服務來決定是否繼續讀)。而不是次次被socket尚有資料的狀態煩擾;寫入資料時也是如此。比如希望將一個資源A寫入到socket。當socket的buffer充足時,epoll_wait會返回這個fd是準備好的。但是資源A此時不一定準備好。如果使用水平觸發,每次經過epoll_wait也總會被打擾。在邊沿觸發下,開發者有機會更精細的定製這裡的控制邏輯。

但不好的一面時,邊沿觸發也大大的提高了程式設計的難度。一不留神,可能就會miss掉處理部分socket資料的機會。如果沒有很好的根據EAGAIN來“重置”一個fd,就會造成此fd永遠沒有新事件產生,進而導致餓死相關的處理程式碼。

水平觸發和邊緣觸發

AIO

相關文章