理清同步/異步、阻塞/非阻塞削彬、BIO全庸、NIO/JAVA NIO、多路復(fù)用IO融痛、AIO壶笼、select、poll和epoll雁刷,題目很亂但思路清晰覆劈。

題目看上去真的很亂,寫之前先貼一張寫之前理出來的思路圖:

題目里那些亂七八糟的名詞都能在圖里找到自己的位置了沛励。 下面就是解釋一下這張圖了墩崩。

從IO開始講吧,先簡單解釋一下IO侯勉。其實(shí)IO這個(gè)概念真的很雜容易混淆鹦筹,我理解的IO是分兩個(gè)大概念的,即網(wǎng)絡(luò)IO和磁盤IO址貌。網(wǎng)絡(luò)IO就是socket網(wǎng)絡(luò)數(shù)據(jù)傳輸铐拐,磁盤IO就是磁盤文件讀寫這些。上圖中的IO理論思想在網(wǎng)絡(luò)IO和磁盤IO中都可以適用的练对,因?yàn)檫@兩個(gè)有很多共同之處遍蟋。

為什么有共同之處呢?可以這么理解螟凭。磁盤IO就是文件讀寫嘛虚青,文件是在磁盤上的要讀到內(nèi)存中,必然會(huì)涉及用戶態(tài)和內(nèi)核態(tài)螺男,這里就不解釋用戶態(tài)和內(nèi)核態(tài)了棒厘,理解起來就是用戶態(tài)問內(nèi)核態(tài)要數(shù)據(jù),那用戶態(tài)就是調(diào)用方下隧,內(nèi)核態(tài)就是被調(diào)用方奢人。而網(wǎng)絡(luò)IO也很相似啊,網(wǎng)絡(luò)IO最簡單的理解就是一個(gè)接口被調(diào)用了淆院,總之會(huì)有一個(gè)socket連接過來何乎,讓被調(diào)用的服務(wù)去干嘛干嘛,就可以理解為這個(gè)socket連接是調(diào)用方,被調(diào)用的服務(wù)當(dāng)然就是被調(diào)用方了支救。畫了一張圖總結(jié)一下:

我們所說的IO通常意義上是指磁盤IO的輸入/輸出流抢野,即I/O流。其實(shí)在磁盤IO體系中不止有流式部分各墨,還有非流式部分蒙保,貼兩張網(wǎng)上的圖:

所以,這么一頓分析下來欲主,一般我們打交道比較多的就是磁盤IO流式部分了,而這么長的名字平時(shí)我們只說IO逝嚎,有點(diǎn)搞混的扁瓢。當(dāng)然網(wǎng)絡(luò)IO和磁盤IO的區(qū)分界限也沒有那么清楚,比如字節(jié)流字符流用于文件讀寫沒有問題补君,但是網(wǎng)絡(luò)IO中也避免不了使用字節(jié)流啊引几,這就看個(gè)人理解了。

上面是理了一下IO挽铁,接下來解釋一下同步/異步和阻塞/非阻塞伟桅。

還是看上面調(diào)用方和被調(diào)用方那張圖,記住關(guān)鍵的一點(diǎn)叽掘,同步/異步是描述調(diào)用方是否等待調(diào)用結(jié)果返回的楣铁,阻塞/非阻塞是描述被調(diào)用方線程狀態(tài)的。

拿磁盤IO舉例:

同步阻塞IO就是用戶態(tài)的線程發(fā)起read()/write()調(diào)用后更扁,會(huì)一直等待調(diào)用結(jié)果返回盖腕,而在內(nèi)核態(tài),要去讀一個(gè)磁盤文件浓镜,數(shù)據(jù)不一定立馬就能準(zhǔn)備好啊溃列,同步阻塞IO就是內(nèi)核態(tài)的線程會(huì)一直能數(shù)據(jù)準(zhǔn)備好再去讀。盜張圖貼一下:

同步非阻塞IO同理用戶態(tài)發(fā)起read()/write()調(diào)用后膛薛,也會(huì)一直等待調(diào)用結(jié)果返回听隐,但是在內(nèi)核態(tài),如果數(shù)據(jù)沒有準(zhǔn)備好哄啄,內(nèi)核態(tài)的線程可不會(huì)等著雅任,就直接干別的去了,那就需要用戶態(tài)的線程一直去詢問數(shù)據(jù)有沒有處理好啊咨跌,一直問一直問這個(gè)就叫輪詢椿访。再貼一張圖:

那什么是IO多路復(fù)用呢?可以看出同步非阻塞IO是需要用戶態(tài)要有一個(gè)線程不停地去輪詢的虑润,這就很消耗CPU資源啊成玫,用戶態(tài)就很不樂意了,就在想能不能這個(gè)輪詢的讓內(nèi)核態(tài)自己去做就好了,這就是IO多路復(fù)用了哭当。所以IO多路復(fù)用是在同步非阻塞IO基礎(chǔ)上的一次演進(jìn)猪腕,即IO多路復(fù)用也必然是同步非阻塞IO。這個(gè)輪詢的活是就是select钦勘、poll和或者epoll這三個(gè)機(jī)制來完成的陋葡,也就是select、poll和或者epoll這三個(gè)是內(nèi)核態(tài)的系統(tǒng)調(diào)用彻采,三種不同的方式去找到準(zhǔn)備好的數(shù)據(jù)腐缤。需要注意的是select和poll是輪詢的方式去找到準(zhǔn)備好的數(shù)據(jù),epoll已經(jīng)不用輪詢了肛响,這個(gè)后面會(huì)說岭粤。既然都是在內(nèi)核態(tài)找到準(zhǔn)備好的數(shù)據(jù)了,更接近OS底層的調(diào)用性能也必然是比在用戶態(tài)的時(shí)候好特笋,既然這樣剃浇,那何必只去找用戶態(tài)某一個(gè)線程需要的數(shù)據(jù)呢,那就替用戶態(tài)所有干等著的線程找準(zhǔn)備好的數(shù)據(jù)吧猎物,這就是多路復(fù)用這個(gè)詞的來源虎囚。

上面是在磁盤IO理解了同步阻塞IO、同步非阻塞IO和多路復(fù)用IO蔫磨,那么在網(wǎng)絡(luò)IO怎么理解呢淘讥?

對于網(wǎng)絡(luò)IO,同步阻塞IO不用說了堤如,一個(gè)socket連接過來了适揉,里面的數(shù)據(jù)并不一定準(zhǔn)備好了,如果被調(diào)用服務(wù)的線程在干等著socket中的數(shù)據(jù)準(zhǔn)備好煤惩,那就是同步阻塞IO嫉嘀。如果這個(gè)服務(wù)線程不等呢?而是去詢問其他socket連接中的數(shù)據(jù)有沒有準(zhǔn)備好魄揉,那這就是同步非阻塞IO剪侮。

網(wǎng)絡(luò)IO和磁盤IO的同步非阻塞IO的理解還是有點(diǎn)區(qū)別的,磁盤IO的同步非阻塞的輪詢操作是由調(diào)用方去做的洛退,而且輪詢的是被調(diào)用方瓣俯,但是網(wǎng)絡(luò)IO的同步非阻塞總不能讓調(diào)用方去輪詢吧,難不成還一遍一遍的socket連接過來兵怯?所以只能被調(diào)用方去輪詢彩匕,而且輪詢的是調(diào)用方即一組socket連接,所以網(wǎng)絡(luò)IO的同步非阻塞IO也可以成為是IO多路復(fù)用媒区,即是被調(diào)用方在輪詢又有多路復(fù)用這個(gè)概念在里面啊驼仪。

JAVA NIO是NIO思想在JAVA領(lǐng)域的實(shí)現(xiàn)掸犬,所以很多人說JAVA NIO是多路復(fù)用IO也沒什么問題。既然是NIO思想在JAVA領(lǐng)域的實(shí)現(xiàn)绪爸,必然在網(wǎng)絡(luò)IO和磁盤IO都是可用的湾碎。在網(wǎng)絡(luò)IO應(yīng)用的關(guān)鍵詞就是Selector,即一組socket連接注冊到上面奠货。在磁盤IO的應(yīng)用關(guān)鍵字就是FileChannel文件通道和Buffer緩沖區(qū)介褥,也是用了select、poll或者epoll這一套递惋。

理清了上面這些概念柔滔,然后就可以了解一下select、poll和epoll萍虽。

1.select

select函數(shù)就是上面說的睛廊,做了遍歷輪詢的活,不止替一個(gè)用戶態(tài)線程找準(zhǔn)備好的數(shù)據(jù)贩挣,而是把很多個(gè)文件描述符fd放進(jìn)一個(gè)set集合中遍歷,就是替多個(gè)用戶態(tài)線程找準(zhǔn)備好的數(shù)據(jù)没酣。當(dāng)然王财,既然是set集合那就有數(shù)量上限,32位機(jī)器上默認(rèn)是1024個(gè)裕便,64位機(jī)器上默認(rèn)是2048個(gè)绒净。貼一張圖:

時(shí)間復(fù)雜度:O(n)

select的缺點(diǎn):

(1)單進(jìn)程可以打開fd有限制;

(2)對socket進(jìn)行掃描時(shí)是線性掃描偿衰,即采用輪詢的方法挂疆,效率較低;

(3)用戶空間和內(nèi)核空間的復(fù)制非常消耗資源下翎;

2.poll

其實(shí)poll調(diào)用過程和select一樣缤言,只不過采用鏈表的方式替換select的set集合去存儲(chǔ)fd,這樣連接數(shù)就沒有限制了视事。時(shí)間復(fù)雜度同樣為O(n)胆萧。

3.epoll

應(yīng)用示例:Nginx。

epoll就不像前面兩個(gè)把fd放進(jìn)一個(gè)集合里去遍歷了俐东,而是采用注冊回調(diào)函數(shù)跌穗,在文件描述就緒的時(shí)候網(wǎng)卡驅(qū)動(dòng)會(huì)去觸發(fā)這個(gè)回調(diào)函數(shù),通知說這個(gè)fd的數(shù)據(jù)已經(jīng)準(zhǔn)備好了虏辫,這就很nice了蚌吸。貼一下圖:

這樣就既沒有連接數(shù)限制,又不用去遍歷輪詢消耗CPU砌庄。而且時(shí)間復(fù)雜度為O(1)羹唠。?

epoll有兩種工作方式:1.水平觸發(fā)(LT)2.邊緣觸發(fā)(ET)?

LT模式:若就緒的事件一次沒有處理完要做的事件奕枢,就會(huì)一直去處理。即就會(huì)將沒有處理完的事件繼續(xù)放回到就緒隊(duì)列之中(即那個(gè)內(nèi)核中的鏈表)肉迫,一直進(jìn)行處理验辞。?

ET模式:就緒的事件只能處理一次,若沒有處理完會(huì)在下次的其它事件就緒時(shí)再進(jìn)行處理喊衫。而若以后再也沒有就緒的事件跌造,那么剩余的那部分?jǐn)?shù)據(jù)也會(huì)隨之而丟失。?

由此可見:ET模式的效率比LT模式的效率要高很多族购。只是如果使用ET模式壳贪,就要保證每次進(jìn)行數(shù)據(jù)處理時(shí),要將其處理完寝杖,不能造成數(shù)據(jù)丟失违施,這樣對編寫代碼的人要求就比較高。?

需要注意的是瑟幕,ET模式只支持非阻塞的讀寫:為了保證數(shù)據(jù)的完整性磕蒲。

到這里IO的同步模型就梳理得差不多了,還有一個(gè)異步模型只盹。

按剛剛的理解辣往,異步模型是需要調(diào)用方發(fā)起調(diào)用動(dòng)作后就不等了,去干別的事殖卑。而我們平常的編程站削,代碼是一行一行寫下來,運(yùn)行的時(shí)候也是一個(gè)線程一行一行的執(zhí)行下來孵稽,這行的結(jié)果沒出來呢線程也不會(huì)去干別的事许起,所以我們?nèi)粘5木幊潭际峭骄幊蹋亲霾坏秸嬲漠惒絀O的菩鲜。顧名思義異步IO需要特殊的異步編程語法园细,現(xiàn)在有的就是協(xié)程,這已經(jīng)涉及我的知識盲區(qū)了接校,就不繼續(xù)寫了珊肃。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市馅笙,隨后出現(xiàn)的幾起案子伦乔,更是在濱河造成了極大的恐慌,老刑警劉巖董习,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烈和,死亡現(xiàn)場離奇詭異,居然都是意外死亡皿淋,警方通過查閱死者的電腦和手機(jī)招刹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門恬试,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人疯暑,你說我怎么就攤上這事训柴。” “怎么了妇拯?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵幻馁,是天一觀的道長。 經(jīng)常有香客問我越锈,道長仗嗦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任甘凭,我火速辦了婚禮稀拐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丹弱。我一直安慰自己德撬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布躲胳。 她就那樣靜靜地躺著蜓洪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪泛鸟。 梳的紋絲不亂的頭發(fā)上蝠咆,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天踊东,我揣著相機(jī)與錄音北滥,去河邊找鬼。 笑死闸翅,一個(gè)胖子當(dāng)著我的面吹牛再芋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坚冀,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼济赎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了记某?” 一聲冷哼從身側(cè)響起司训,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎液南,沒想到半個(gè)月后壳猜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡滑凉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年统扳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喘帚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咒钟,死狀恐怖吹由,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情朱嘴,我是刑警寧澤倾鲫,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站腕够,受9級特大地震影響级乍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帚湘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一玫荣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧大诸,春花似錦捅厂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贿堰,卻和暖如春辙芍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背羹与。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工故硅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纵搁。 一個(gè)月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓吃衅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親腾誉。 傳聞我的和親對象是個(gè)殘疾皇子徘层,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容