聊聊同步拂铡、異步陨溅、阻塞與非阻塞

來(lái)源:伯樂(lè)在線專(zhuān)欄作者 - 陶邦仁

鏈接:http://blog.jobbole.com/99765/

點(diǎn)擊 → 了解如何加入專(zhuān)欄作者

近來(lái)遇到了一些常見(jiàn)的概念终惑,尤其是網(wǎng)絡(luò)編程方面的概念,如:阻塞门扇、非阻塞雹有、異步I/O等等,對(duì)于這些概念自己也沒(méi)有太清晰的認(rèn)識(shí)臼寄,只是很模糊的概念件舵,說(shuō)了解吧也了解,但是要讓自己準(zhǔn)確的描述概念方面的具體細(xì)節(jié)脯厨,卻說(shuō)的不那么準(zhǔn)確铅祸,這也是自己在這幾個(gè)方面也沒(méi)有細(xì)細(xì)考究過(guò)的原因吧。經(jīng)過(guò)看了些這幾個(gè)概念的資料,發(fā)現(xiàn)同步临梗、異步涡扼、阻塞、非阻塞的概念其實(shí)也并不難以理解盟庞,在此寫(xiě)下此文吃沪,歡迎拍磚,希望多多交流什猖。

1 同步與異步

首先來(lái)解釋同步和異步的概念票彪,這兩個(gè)概念與消息的通知機(jī)制有關(guān)。也就是同步與異步主要是從消息通知機(jī)制角度來(lái)說(shuō)的不狮。

1.1 概念描述

所謂同步就是一個(gè)任務(wù)的完成需要依賴(lài)另外一個(gè)任務(wù)時(shí)降铸,只有等待被依賴(lài)的任務(wù)完成后,依賴(lài)的任務(wù)才能算完成摇零,這是一種可靠的任務(wù)序列推掸。要么成功都成功,失敗都失敗驻仅,兩個(gè)任務(wù)的狀態(tài)可以保持一致谅畅。

所謂異步是不需要等待被依賴(lài)的任務(wù)完成,只是通知被依賴(lài)的任務(wù)要完成什么工作噪服,依賴(lài)的任務(wù)也立即執(zhí)行毡泻,只要自己完成了整個(gè)任務(wù)就算完成了。至于被依賴(lài)的任務(wù)最終是否真正完成粘优,依賴(lài)它的任務(wù)無(wú)法確定牙捉,所以它是不可靠的任務(wù)序列。

1.2 消息通知

異步的概念和同步相對(duì)敬飒。當(dāng)一個(gè)同步調(diào)用發(fā)出后邪铲,調(diào)用者要一直等待返回消息(結(jié)果)通知后,才能進(jìn)行后續(xù)的執(zhí)行无拗;當(dāng)一個(gè)異步過(guò)程調(diào)用發(fā)出后带到,調(diào)用者不能立刻得到返回消息(結(jié)果)。實(shí)際處理這個(gè)調(diào)用的部件在完成后英染,通過(guò)狀態(tài)揽惹、通知和回調(diào)來(lái)通知調(diào)用者。

這里提到執(zhí)行部件和調(diào)用者通過(guò)三種途徑返回結(jié)果:狀態(tài)四康、通知和回調(diào)搪搏。使用哪一種通知機(jī)制,依賴(lài)于執(zhí)行部件的實(shí)現(xiàn)闪金,除非執(zhí)行部件提供多種選擇疯溺,否則不受調(diào)用者控制论颅。

如果執(zhí)行部件用狀態(tài)來(lái)通知,那么調(diào)用者就需要每隔一定時(shí)間檢查一次囱嫩,效率就很低(有些初學(xué)多線程編程的人恃疯,總喜歡用一個(gè)循環(huán)去檢查某個(gè)變量的值,這其實(shí)是一種很?chē)?yán)重的錯(cuò)誤)墨闲;

如果是使用通知的方式今妄,效率則很高,因?yàn)閳?zhí)行部件幾乎不需要做額外的操作鸳碧。至于回調(diào)函數(shù)盾鳞,其實(shí)和通知沒(méi)太多區(qū)別。

1.3 場(chǎng)景比喻

舉個(gè)例子瞻离,比如我去銀行辦理業(yè)務(wù)腾仅,可能會(huì)有兩種方式:

選擇排隊(duì)等候;

另種選擇取一個(gè)小紙條上面有我的號(hào)碼琐脏,等到排到我這一號(hào)時(shí)由柜臺(tái)的人通知我輪到我去辦理業(yè)務(wù)了;

第一種:前者(排隊(duì)等候)就是同步等待消息通知缸兔,也就是我要一直在等待銀行辦理業(yè)務(wù)情況日裙;

第二種:后者(等待別人通知)就是異步等待消息通知。在異步消息處理中惰蜜,等待消息通知者(在這個(gè)例子中就是等待辦理業(yè)務(wù)的人)往往注冊(cè)一個(gè)回調(diào)機(jī)制昂拂,在所等待的事件被觸發(fā)時(shí)由觸發(fā)機(jī)制(在這里是柜臺(tái)的人)通過(guò)某種機(jī)制(在這里是寫(xiě)在小紙條上的號(hào)碼,喊號(hào))找到等待該事件的人抛猖。

2 阻塞與非阻塞

阻塞和非阻塞這兩個(gè)概念與程序(線程)等待消息通知(無(wú)所謂同步或者異步)時(shí)的狀態(tài)有關(guān)格侯。也就是說(shuō)阻塞與非阻塞主要是程序(線程)等待消息通知時(shí)的狀態(tài)角度來(lái)說(shuō)的。

2.1 概念描述

阻塞調(diào)用是指調(diào)用結(jié)果返回之前财著,當(dāng)前線程會(huì)被掛起联四,一直處于等待消息通知,不能夠執(zhí)行其他業(yè)務(wù)撑教。函數(shù)只有在得到結(jié)果之后才會(huì)返回朝墩。

有人也許會(huì)把阻塞調(diào)用和同步調(diào)用等同起來(lái),實(shí)際上它們是不同的伟姐。

對(duì)于同步調(diào)用來(lái)說(shuō)收苏,很多時(shí)候當(dāng)前線程可能還是激活的,只是從邏輯上當(dāng)前函數(shù)沒(méi)有返回而已愤兵,此時(shí)鹿霸,這個(gè)線程可能也會(huì)處理其他的消息。還有一點(diǎn)秆乳,在這里先擴(kuò)展下:

如果這個(gè)線程在等待當(dāng)前函數(shù)返回時(shí)懦鼠,仍在執(zhí)行其他消息處理,那這種情況就叫做同步非阻塞;

如果這個(gè)線程在等待當(dāng)前函數(shù)返回時(shí)葛闷,沒(méi)有執(zhí)行其他消息處理憋槐,而是處于掛起等待狀態(tài),那這種情況就叫做同步阻塞淑趾;

所以同步的實(shí)現(xiàn)方式會(huì)有兩種:同步阻塞阳仔、同步非阻塞;同理扣泊,異步也會(huì)有兩種實(shí)現(xiàn):異步阻塞近范、異步非阻塞;

對(duì)于阻塞調(diào)用來(lái)說(shuō)延蟹,則當(dāng)前線程就會(huì)被掛起等待當(dāng)前函數(shù)返回评矩;

非阻塞和阻塞的概念相對(duì)應(yīng),指在不能立刻得到結(jié)果之前阱飘,該函數(shù)不會(huì)阻塞當(dāng)前線程斥杜,而會(huì)立刻返回。雖然表面上看非阻塞的方式可以明顯的提高CPU的利用率沥匈,但是也帶了另外一種后果就是系統(tǒng)的線程切換增加蔗喂。增加的CPU執(zhí)行時(shí)間能不能補(bǔ)償系統(tǒng)的切換成本需要好好評(píng)估。

2.2 場(chǎng)景比喻

繼續(xù)上面的那個(gè)例子高帖,不論是排隊(duì)還是使用號(hào)碼等待通知缰儿,如果在這個(gè)等待的過(guò)程中,等待者除了等待消息通知之外不能做其它的事情散址,那么該機(jī)制就是阻塞的乖阵,表現(xiàn)在程序中,也就是該程序一直阻塞在該函數(shù)調(diào)用處不能繼續(xù)往下執(zhí)行。

相反预麸,有的人喜歡在銀行辦理這些業(yè)務(wù)的時(shí)候一邊打打電話發(fā)發(fā)短信一邊等待瞪浸,這樣的狀態(tài)就是非阻塞的,因?yàn)樗?等待者)沒(méi)有阻塞在這個(gè)消息通知上吏祸,而是一邊做自己的事情一邊等待默终。

但是需要注意了,同步非阻塞形式實(shí)際上是效率低下的犁罩,想象一下你一邊打著電話一邊還需要抬頭看到底隊(duì)伍排到你了沒(méi)有齐蔽。如果把打電話和觀察排隊(duì)的位置看成是程序的兩個(gè)操作的話,這個(gè)程序需要在這兩種不同的行為之間來(lái)回的切換床估,效率可想而知是低下的含滴;而異步非阻塞形式卻沒(méi)有這樣的問(wèn)題,因?yàn)榇螂娫捠悄?等待者)的事情丐巫,而通知你則是柜臺(tái)(消息觸發(fā)機(jī)制)的事情谈况,程序沒(méi)有在兩種不同的操作中來(lái)回切換勺美。

3 同步/異步與阻塞/非阻塞

同步阻塞形式效率是最低的,

拿上面的例子來(lái)說(shuō)碑韵,就是你專(zhuān)心排隊(duì)赡茸,什么別的事都不做。

實(shí)際程序中:就是未對(duì)fd 設(shè)置O_NONBLOCK標(biāo)志位的read/write 操作祝闻;

異步阻塞形式如果在銀行等待辦理業(yè)務(wù)的人采用的是異步的方式去等待消息被觸發(fā)(通知)占卧,也就是領(lǐng)了一張小紙條,假如在這段時(shí)間里他不能離開(kāi)銀行做其它的事情联喘,那么很顯然华蜒,這個(gè)人被阻塞在了這個(gè)等待的操作上面;

異步操作是可以被阻塞住的豁遭,只不過(guò)它不是在處理消息時(shí)阻塞叭喜,而是在等待消息通知時(shí)被阻塞。

比如select 函數(shù)蓖谢,假如傳入的最后一個(gè)timeout參數(shù)為NULL捂蕴,那么如果所關(guān)注的事件沒(méi)有一個(gè)被觸發(fā),程序就會(huì)一直阻塞在這個(gè)select 調(diào)用處闪幽。

同步非阻塞形式實(shí)際上是效率低下的

想象一下你一邊打著電話一邊還需要抬頭看到底隊(duì)伍排到你了沒(méi)有啥辨,如果把打電話和觀察排隊(duì)的位置看成是程序的兩個(gè)操作的話,這個(gè)程序需要在這兩種不同的行為之間來(lái)回的切換沟使,效率可想而知是低下的委可。

很多人會(huì)寫(xiě)阻塞的read/write 操作渊跋,但是別忘了可以對(duì)fd設(shè)置O_NONBLOCK 標(biāo)志位腊嗡,這樣就可以將同步操作變成非阻塞的了。

異步非阻塞形式效率更高拾酝,

因?yàn)榇螂娫捠悄?等待者)的事情燕少,而通知你則是柜臺(tái)(消息觸發(fā)機(jī)制)的事情,程序沒(méi)有在兩種不同的操作中來(lái)回切換蒿囤。

比如說(shuō)客们,這個(gè)人突然發(fā)覺(jué)自己煙癮犯了,需要出去抽根煙材诽,于是他告訴大堂經(jīng)理說(shuō)底挫,排到我這個(gè)號(hào)碼的時(shí)候麻煩到外面通知我一下(注冊(cè)一個(gè)回調(diào)函數(shù)),那么他就沒(méi)有被阻塞在這個(gè)等待的操作上面脸侥,自然這個(gè)就是異步+非阻塞的方式了建邓。

如果使用異步非阻塞的情況,比如aio_*組的操作睁枕,當(dāng)發(fā)起一個(gè)aio_read操作時(shí)官边,函數(shù)會(huì)馬上返回不會(huì)被阻塞沸手,當(dāng)所關(guān)注的事件被觸發(fā)時(shí)會(huì)調(diào)用之前注冊(cè)的回調(diào)函數(shù)進(jìn)行處理。

很多人會(huì)把同步和阻塞混淆注簿,我想是因?yàn)楹芏鄷r(shí)候同步操作會(huì)以阻塞的形式表現(xiàn)出來(lái)契吉,比如很多人會(huì)寫(xiě)阻塞的read/write操作,但是別忘了可以對(duì)fd設(shè)置O_NONBLOCK標(biāo)志位诡渴,這樣就可以將同步操作變成非阻塞的了捐晶。但最根本是因?yàn)闆](méi)有區(qū)分這兩個(gè)概念,比如阻塞的read/write操作中玩徊,其實(shí)是把消息通知機(jī)制和等待消息通知的狀態(tài)結(jié)合在了一起租悄,在這里所關(guān)注的消息就是fd是否可讀/寫(xiě),而等待消息通知的狀態(tài)則是對(duì)fd可讀/寫(xiě)等待過(guò)程中程序(線程)的狀態(tài)恩袱。當(dāng)我們將這個(gè)fd設(shè)置為非阻塞的時(shí)候泣棋,read/write操作就不會(huì)在等待消息通知這里阻塞,如果fd不可讀/寫(xiě)則操作立即返回畔塔。

同樣的潭辈,很多人也會(huì)把異步和非阻塞混淆,因?yàn)楫惒讲僮饕话愣疾粫?huì)在真正的IO操作處被阻塞澈吨,比如如果用select函數(shù)把敢,當(dāng)select返回可讀時(shí)再去read一般都不會(huì)被阻塞,而是在select函數(shù)調(diào)用處阻塞谅辣。

4 小明的故事

對(duì)上面所講的概念再次進(jìn)行一個(gè)場(chǎng)景梳理修赞,上面已經(jīng)明確說(shuō)明,同步/異步關(guān)注的是消息通知的機(jī)制桑阶,而阻塞/非阻塞關(guān)注的是程序(線程)等待消息通知時(shí)的狀態(tài)柏副。以小明下載文件打個(gè)比方,從這兩個(gè)關(guān)注點(diǎn)來(lái)再次說(shuō)明這兩組概念蚣录,希望能夠更好的促進(jìn)大家的理解割择。

同步阻塞:小明一直盯著下載進(jìn)度條,到 100% 的時(shí)候就完成萎河。

同步體現(xiàn)在:等待下載完成通知荔泳;

阻塞體現(xiàn)在:等待下載完成通知過(guò)程中,不能做其他任務(wù)處理虐杯;

同步非阻塞:小明提交下載任務(wù)后就去干別的玛歌,每過(guò)一段時(shí)間就去瞄一眼進(jìn)度條,看到 100% 就完成擎椰。

同步體現(xiàn)在:等待下載完成通知支子;

非阻塞體現(xiàn)在:等待下載完成通知過(guò)程中,去干別的任務(wù)了确憨,只是時(shí)不時(shí)會(huì)瞄一眼進(jìn)度條译荞;【小明必須要在兩個(gè)任務(wù)間切換瓤的,關(guān)注下載進(jìn)度】

異步阻塞:小明換了個(gè)有下載完成通知功能的軟件,下載完成就“锻碳撸”一聲圈膏。不過(guò)小明仍然一直等待“叮”的聲音(看起來(lái)很傻篙骡,不是嗎)稽坤。

異步體現(xiàn)在:下載完成“叮”一聲通知糯俗;

阻塞體現(xiàn)在:等待下載完成“赌蛲剩”一聲通知過(guò)程中,不能做其他任務(wù)處理得湘;

異步非阻塞:仍然是那個(gè)會(huì)“墩攘幔”一聲的下載軟件,小明提交下載任務(wù)后就去干別的淘正,聽(tīng)到“栋诼恚”的一聲就知道完成了。

異步體現(xiàn)在:下載完成“逗柽海”一聲通知囤采;

非阻塞體現(xiàn)在:等待下載完成“叮”一聲通知過(guò)程中惩淳,去干別的任務(wù)了蕉毯,只需要接收“叮”聲通知即可思犁;【軟件處理下載任務(wù)代虾,小明處理其他任務(wù),不需關(guān)注進(jìn)度抒倚,只需接收軟件“逗肿牛”聲通知坷澡,即可】

也就是說(shuō)托呕,同步/異步是“下載完成消息”通知的方式(機(jī)制),而阻塞/非阻塞則是在等待“下載完成消息”通知過(guò)程中的狀態(tài)(能不能干其他任務(wù))频敛,在不同的場(chǎng)景下项郊,同步/異步、阻塞/非阻塞的四種組合都有應(yīng)用斟赚。

所以着降,綜上所述,同步和異步僅僅是關(guān)注的消息如何通知的機(jī)制拗军,而阻塞與非阻塞關(guān)注的是等待消息通知時(shí)的狀態(tài)任洞。也就是說(shuō)蓄喇,同步的情況下,是由處理消息者自己去等待消息是否被觸發(fā)交掏,而異步的情況下是由觸發(fā)機(jī)制來(lái)通知處理消息者妆偏,所以在異步機(jī)制中,處理消息者和觸發(fā)機(jī)制之間就需要一個(gè)連接的橋梁:

在銀行的例子中盅弛,這個(gè)橋梁就是小紙條上面的號(hào)碼钱骂。

在小明的例子中,這個(gè)橋梁就是軟件“杜才簦”的聲音见秽。

最后,請(qǐng)大家注意理解“消息通知機(jī)制”和“等待消息通知時(shí)的狀態(tài)”這兩個(gè)概念讨盒,這是理解四個(gè)概念的關(guān)鍵所在解取。

專(zhuān)欄作者簡(jiǎn)介點(diǎn)擊 → 加入專(zhuān)欄作者

陶邦仁:專(zhuān)注于后端技術(shù)研究,前端技術(shù)略有涉獵返顺,熱衷于構(gòu)建高性能肮蛹、高可用網(wǎng)站,對(duì)平臺(tái)服務(wù)化创南、分布式服務(wù)伦忠、分布式存儲(chǔ)等方面的解決方案。目前就職于千丁互聯(lián)稿辙,任技術(shù)經(jīng)理一職昆码,負(fù)責(zé)社區(qū)產(chǎn)品技術(shù)研發(fā)。曾就職于京東邻储,負(fù)責(zé)庫(kù)存組緩存方案技術(shù)實(shí)現(xiàn)赋咽;曾就職于百度糯米,負(fù)責(zé)PC首頁(yè)吨娜、APP個(gè)性化排單服務(wù)化解決方案脓匿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市宦赠,隨后出現(xiàn)的幾起案子陪毡,更是在濱河造成了極大的恐慌,老刑警劉巖勾扭,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毡琉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡妙色,警方通過(guò)查閱死者的電腦和手機(jī)桅滋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)身辨,“玉大人丐谋,你說(shuō)我怎么就攤上這事芍碧。” “怎么了号俐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵师枣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我萧落,道長(zhǎng)践美,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任找岖,我火速辦了婚禮陨倡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘许布。我一直安慰自己兴革,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布蜜唾。 她就那樣靜靜地躺著杂曲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪袁余。 梳的紋絲不亂的頭發(fā)上擎勘,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音颖榜,去河邊找鬼棚饵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛掩完,可吹牛的內(nèi)容都是我干的噪漾。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼且蓬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼欣硼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起恶阴,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤诈胜,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后存淫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體耘斩,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沼填,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年桅咆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坞笙。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岩饼,死狀恐怖荚虚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情籍茧,我是刑警寧澤版述,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站寞冯,受9級(jí)特大地震影響渴析,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吮龄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一俭茧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧漓帚,春花似錦母债、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至昧辽,卻和暖如春衙熔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搅荞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工青责, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人取具。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓脖隶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親暇检。 傳聞我的和親對(duì)象是個(gè)殘疾皇子产阱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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