通俗系列之同步、异步、阻塞和非阻塞
前言
在日常的開發中,經常出現同步、異步、阻塞和非阻塞等概念。有些人搞不清楚什么代碼是同步,什么代碼是異步。有些人說我用異步了啊,為什么效率還是沒提高呢?也許你是用異步了,但是可能是異步阻塞了。有些人一聽說異步好,就不管三七二十一,所有方法全部改成異步,然后就會產生新的問題。歸根結底還是對同步、異步、阻塞和非阻塞的概念不理解。
那究竟什么是同步、異步、阻塞和非阻塞呢?我決定嘗試用比較通俗的例子舉例來解釋一下,于是便有了這篇文章。
同步
概念
什么是同步?同步就是一個任務的完成依賴于另外一個任務,只有被依賴的任務完成后,那么依賴的任務才能繼續完成。
這是一種非常可靠的任務序列,要么都成功,要么都失敗。
就和以前的瀑布式開發一樣,你要做一個項目,一定要嚴格按照需求、分析、設計、編碼、測試的步驟順序執行,如果其中有一個問題卡住了,那么后邊就無法繼續,如果其中有一個環節是搞錯了,那么這個項目也就可能死掉了。
同步又分同步阻塞和同步非阻塞,接下來將依次舉例解釋。
同步阻塞
同步阻塞就是調用方在等待另一個任務的結果返回來之前,什么事也沒做,就是死等,直到返回,而且具體要等待的結果是用來干嘛的,如果不返回,是不知道的。
舉例:
快到飯點了,老王很餓,來到了一家飯店,老王跟老板說來份蛋炒飯。
然后老板就是開始做,而老王就一直站在出飯的窗口等著,期間什么也沒干,就是等著,直到老板把飯做好。
說明:
數據調用方:老王 (主線程)
數據持有方:飯店老板
要獲得的數據:蛋炒飯
同步:老王等著老板把飯做好
阻塞:老王在等著,期間什么也沒做
這種調用方式很常見,這是以前普遍的方式,流水線式調用。
如果老王就這樣等著,那么效率是很低的。
同步非阻塞
同步非阻塞就是,你在等一件事A的結果時,可以繼續去干另外一件事B。但是你需要時不時的回來瞧一瞧A的結果是否返回了。
程序上通常都是用輪詢去獲取A事件是否完成并返回結果。
舉例:
快到飯點了,老王很餓,來到了一家飯店,老王跟老板說來份蛋炒飯。
然后老板就是開始做,而老王呢,就跑到飯店的門頭透透氣,順便刷刷微博,但是老王需要時不時的跑進去問問老板飯好了沒有
說明:
數據調用方:老王 (主線程)
數據持有方:飯店老板
要獲得的數據:蛋炒飯
同步:老王等著老板把飯做好
非阻塞:老王等老板把飯做好,但是并不是站著死等,而是出門透透氣,刷刷微博
這種調用方式,一般在同步操作中,中間需要處理一個比較耗時的操作時,通常是另外開辟一個線程去處理這個比較耗時的操作,但是后邊需要自己去輪詢另外一個線程的執行結果是否完成。
就比如上邊,飯店老板做飯比較耗時,老王并沒有一直等著,而是出門刷手機,但是飯有沒有做好他需要時不時的跑進去問問,需要切換自己的位置。
異步
概念
異步就是調用方不需要一直等待被依賴的操作完成,可以繼續干其他事情,當被依賴的操作完成后,會自動通知調用方。
調用異步操作時,被依賴的操作會直接返回一個任務或承諾給調用方,然后調用方會繼續執行后邊的操作。等被依賴的操作完成后,會通知調用方
日常生活中就很常見,比如:
領導給你安排一個任務,可能會說:小明你把xx項目的方案寫一下,寫完之后xx項目的相關人員一起去會議室開個會。小明肯定不能立即把方案寫完,此時就會回答領導,“好的領導”。然后領導繼續干自己的事,小明就去寫方案,寫完之后小明去通知領導,然后領導拿到方案后通知相關人員一起開會。
異步阻塞
異步阻塞就是雖然被依賴項完成時會通知調用方,但是調用方并沒有繼續去干其他事,而是依舊繼續在那等著。
舉例:
快到飯點了,老王很餓,來到了一家飯店,老王跟老板說來份蛋炒飯。
老板在點菜機上下了單,并給了老王一個號,告訴老王等飯做好后,會叫號通知的。
雖然會通知,但是老王很餓很著急,依舊站在出飯窗口等著。
說明:
數據調用方:老王 (主線程)
數據持有方:飯店老板
要獲得的數據:蛋炒飯
異步:飯做好了會叫號通知的。
阻塞:雖然會通知,但是老王依舊站那等著飯做好,期間什么也沒做。
目前,現實社會中大部分場景都有了叫號功能,不需要一直排隊等著。但是也免不了有個別人比較著急,即便是會叫號也一直站旁邊等著。
異步非阻塞
異步非阻塞就是被依賴項完成時會通知調用方,調用方無需等待被依賴項,可以繼續干其他跟依賴項結果無關的事。
舉例:
快到飯點了,老王很餓,來到了一家飯店,老王跟老板說來份蛋炒飯。
老板在點菜機上下了單,并給了老王一個單子,單子上是5號,告訴老王飯做好后,會叫這個號通知的。
然后,老王拿著號找了個位置,刷起了新聞,期間還出門打了個電話,處理了一些工作上的事。突然老王聽到叫號機通知5號的飯做好了,然后老王去窗口拿自己的飯。
說明:
數據調用方:老王 (主線程)
數據持有方:飯店老板
要獲得的數據:蛋炒飯
異步:飯做好了會叫號通知的。
非阻塞:因為飯做好后會叫號,所以老王并沒有一直站那等著,期間找了個位置刷起了新聞,還出去接了個電話
這種效率是最高的,你做你的飯,我可以繼續干不依賴于飯的事。你做好飯了叫我就行。
異步在目前的前后端開發中都挺常見的。
前端中通常會返回一個Promise(承諾)對象,.NET后端通常返回一個Task(任務),兩個其實是一個意思。接下來以前端來舉例例如:
//AService.js?有兩個方法,一個是獲取數據getData(),一個是做一些耗時操作doSomething() async?getData(){return?await?GetMyData()//該方法需要查數據比較耗時 } //該方法就寫一些日志 async?doSomething(){await?writeLog() }//B.vue頁面 inint?(){//?1?異步執行某個操作doSomething()?// 2 異步獲取數據,然后對數據做xxx處理。代碼的閱讀和現實的語義是一樣的。getData().then(res?=>?{//可以針對res做相應的處理})//3//... 不依賴于1、2的同步操作。 }//上邊doSomething()和getData().then()都會立即返回一個Promise(承諾),承諾會完成.上邊1、2都是瞬間完成的,返回了一個Promise(承諾)。既然叫承諾,那就很好理解了,我承諾會完成,但不是立即完成。
就比如開會的時候領導說,接下來安排一下任務:
張三,你把A項目的方案寫一下,寫完跟我講一下,我們一起開會討論一下,張三說”好的“。此時張三只是給領導了一個承諾,并沒有立即完成。(異步)
李四,你等會把B項目部署一下,看看運行效果。李四說”好的“。此時李四也是一個承諾,并沒有完成B項目部署。(異步)
然后領導將會議記錄和任務安排發了給大家。(同步)
上邊的3并不依賴于1、2,領導不需要非要等張三把A項目方案寫好,也不需要等李四把B項目部署好,再將會議記錄和任務安排發給大家。
總結
以上是生活随笔為你收集整理的通俗系列之同步、异步、阻塞和非阻塞的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 边缘计算k8s集群之SuperEdge
- 下一篇: 使用 Tye 辅助开发 k8s 应用竟如