多執行緒隙 IO模型(BIO NIO AIO)

2022-01-15 19:17:25 字數 1666 閱讀 1325

同步,非同步,是描述被呼叫方的。阻塞,非阻塞,是描述呼叫方的。 同步不一定阻塞,非同步也不一定非阻塞。沒有必然關係。

舉個簡單的例子:

1 老張把水壺放到火上,一直在水壺旁等著水開。(同步阻塞) 

2 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞)

3 老張把響水壺放到火上,一直在水壺旁等著水開。(非同步阻塞) 

4 老張把響水壺放到火上,去客廳看電視,水壺響之前不再去看它了,響了再去拿壺。(非同步非阻塞) 1和2的區別是,呼叫方在得到返回之前所做的事情不一行。 1和3的區別是,被呼叫方對於燒水的處理不一樣。

非阻塞io,將阻塞變為非阻塞,那就是使用者程序在發起系統呼叫時指定為非阻塞,核心接收到請求後,就會立即返回,然後使用者程序通過輪詢的方式來拉取處理結果

非阻塞io雖然相對於阻塞io大幅提公升了效能,但依舊不是完美的解決方案,其依然存在效能問題,也就是頻繁的輪詢導致頻繁的系統呼叫,會耗費大量的cpu資源。比如當併發很高時,假設有1000個併發,那麼單位時間迴圈內將會有1000次系統呼叫去輪詢執行結果,而實際上可能只有2個請求結果執行完畢,這就會有998次無效的系統呼叫,造成嚴重的效能浪費。有問題就要解決,那nio問題的本質就是頻繁輪詢導致的無效系統呼叫。

客戶端傳送請求都會註冊到多路復用器上,多路復用器輪詢到連線有i/o請求時才啟動乙個執行緒進行處理。

io多路復用之select/poll:

select是核心提供的系統呼叫,它支援一次查詢多個系統呼叫的可用狀態,當任意乙個結果狀態可用時就會返回,使用者程序再發起一次系統呼叫進行資料讀取。換句話說,就是nio中n次的系統呼叫,借助select,只需要發起一次系統呼叫就夠了。但是,select有乙個限制,就是存在連線數限制,針對於此,又提出了poll。其與select相比,主要是解決了連線限制。

select/poll 雖然解決了nio重複無效系統呼叫用的問題,但同時又引入了新的問題。問題是:

使用者空間和核心空間之間,大量的資料拷貝

核心迴圈遍歷io狀態,浪費cpu時間

換句話說,select/poll雖然減少了使用者程序的發起的系統呼叫,但核心的工作量只增不減。在高併發的情況下,核心的效能問題依舊。所以select/poll的問題本質是:核心存在無效的迴圈遍歷。

io多路復用之epoll:

針對select/pool引入的問題,我們把解決問題的思路轉回到核心上,如何減少核心重複無效的迴圈遍歷呢?變主動為被動,基於事件驅動來實現。

與nio不同,當進行讀寫操作時,只須直接呼叫api的read或write方法即可。這兩種方法均為非同步的,對於讀操作而言,當有流可讀取時,作業系統會將可讀的流傳入read方法的緩衝區,並通知應用程式;對於寫操作而言,當作業系統將write方法傳遞的流寫入完畢時,作業系統主動通知應用程式。 即可以理解為,read/write方法都是非同步的,完成後會主動呼叫**函式。

bio方式適用於連線數目比較小且固定的架構,這種方式對伺服器資源要求比較高,併發侷限於應用中,jdk1.4以前的唯一選擇,但程式直觀簡單易理解。•nio方式適用於連線數目多且連線比較短(輕操作)的架構,比如聊天伺服器,併發侷限於應用中,程式設計比較複雜,jdk1.4開始支援。•aio方式使用於連線數目多且連線比較長(重操作)的架構,比如相簿伺服器,充分呼叫os參與併發操作,程式設計比較複雜,jdk7開始支援。

參考:

執行緒 IO 模型

一 redis 單執行緒為什麼還能這麼快?因為它所有的資料都在記憶體中,所有的運算都是記憶體級別的運算。正因為 redis 是單執行緒,所以要小心使用 redis 指令,對於那些時間複雜度為 o n 級別的指令,一定要謹慎使用,一不小心就可能會導致 redis 卡頓。redis 單執行緒如何處理那麼...

11執行緒 多執行緒模型

一 什麼是執行緒 為什麼要引入執行緒 二 引入執行緒機制後的變化 三 執行緒有的屬性 四 執行緒的實現方式 五 多執行緒模型 1 執行緒引入原因分析 2 執行緒 可以把執行緒理解為輕量級程序。執行緒是基本的cpu執行單元,也是程式執行流的最小單元。引入執行緒後不僅程序可以併發,程序內的執行緒也可以併...

網路程式設計3 多程序 多執行緒程式設計 IO模型

select系統呼叫第乙個引數需要 1先說明一下,在windows中,並不要求select函式的第乙個引數總應該是fdmax 1 在windows下,給定 1就行 那linux中為什麼又是呢?這就涉及到linux select第乙個引數的函式 待測試的描述集的總個數。但要注意,待測試的描述集總是從0...