觀念詳解『阻塞、非阻塞、同步及異步』

更新於 發佈於 閱讀時間約 4 分鐘

預備知識


一切從任務(行程或執行緒)狀態變化說起

計算機由單個程式到多個程式運行及整批系統到分時系統,這一切都是為了更有效率地使用計算機,現在我們討論在單核情況下的計算機是如何運作的,每個任務的運行都被分配一個時間片段,時間到就會發起系統中斷告知系統,讓CPU可以去執行其他任務,由於每個時間片段都時間都非常短,所以我們會覺得好像所有的任務都是同時運作的,但其實不然,這些任務是一個接著一個按照順序被執行的,我們把這個現象稱之為並行(中國用語:並發)。如果說在時間片段期間我們發起會阻塞當前任務的系統調用,那麼當前任務所有相關資訊都會被保存,然後被放入等待佇列當中,該任務狀態為阻塞,排班程式會為我們分派其他任務並且配置CPU給其使用,而這個被作業系統阻塞的任務其發起的系統調用會經由DMA來進行處理資料的交換,等待完成搬移資料會發出I/O中斷告知作業系統,此時作業系統將會從該任務暫停的地方開始繼續執行。
以下是任務狀態流程圖:
任務狀態

並行與平行

並行(Concurrency),中國用語並發
任務在不同時間點被分配CPU來執行處理,也就是說在同一個時間點,任務不可能同時執行的。
平行(Parallelism),中國用語並行
每一個任務都可以分別被分配至不同的CPU來執行處理,也就是說在同一個時間點下,被分配CPU的任務可以同時執行。平行是基於多核處理器才能實現的
用一張圖說明並行與平行:
並行與平行

I/O與CPU傾向任務

I/O傾向任務(I/O-bound )
CPU執行時間短,I/O執行時間長。(優先權重較CPU傾向任務高)
CPU傾向任務(CPU-bound )
CPU執行時間長,I/O執行時間短。

阻塞、非阻塞


調用阻塞I/O

作業系統層面
任務調用阻塞I/O後,系統不會返回結果,會將當前任務相關資訊保存,並且將CPU使用權歸還,讓CPU執行其他任務,而該任務進入等待佇列,此時狀態為阻塞態,並且等待處理I/O的控制器處理完資料發出中斷告知系統,系統才會返回結果。
程式層面
因為此刻任務為阻塞態,所以什麼事都不做,就只有等待,接收到系統返回的結果後,此任務才能繼續往下執行。
調用阻塞I/O

調用非阻塞I/O

作業系統層面
任務調用非阻塞I/O後,系統會立即返回一結果或一個錯誤,不會將當前任務阻塞,此任務仍然被CPU執行著,佔用著CPU,CPU會一直處理狀態判斷,接收來自應用層面不斷輪詢的非阻塞調用。
程式層面
此任務透過不斷輪詢的方式,向系統檢查是否有結果,而系統會不斷返回結果給該任務。
調用非阻塞I/O

阻塞與非阻塞的差異

  • 阻塞I/O不能進行並行操作的,很重要在這裡我指的是該任務本身的程式,而不是利用作業系統的多行程/多執行緒來實現並行操作,對於非阻塞I/O來講,可以實現程式本身的並行操作,這就是為什麼非阻塞I/O執行效率比較高的一個原因。
  • 非阻塞I/O調用後會立即返回結果或一個錯誤,而阻塞I/O調用後則不會立即返回
  • 調用非阻塞I/O的任務,仍然佔據著CPU,所以不會被阻塞,而調用阻塞I/O的任務會釋出CPU的使用權,進入阻塞狀態

同步、異步


什麼是同步?

以例子來說,現在在腳本中有兩個函數A與B,其中在A中我們調用B函數,A函數必須等到B函數執行完,返回結果後,A函數才能繼續執行,這個期間A函數必須等待。同步有個特色那就是等待,也就是說他是順序執行一個接著一個。
同步執行結果

什麼是異步

當一個異步方法調用發出後,會立即返回一個錯誤或結果,讓其回到應用本身可以繼續往下執行,如果說該應用不只發出一個異步調用,彼此之間不需要等待誰先完成才能執行下一個,它們是平行操作的,執行結果誰先返回不一定,這就是異步的特色。
以下我們來看一下這段程式碼的執行結果:
異步執行結果
可以發現上圖的異步執行結果,我們對其發出了兩個異步調用,可以看到它們的返回順序不一致,這就是異步的特色,讓其可以平行處理,不需要彼此等待。

參考來源

  1. 《深入淺出node.js》。朴靈。北京。人民郵電出版社。
  2. 【操作系统】詳解阻塞、非阻塞、同步、異步
  3. 行程管理『行程與執行緒概念
即將進入廣告,捲動後可繼續閱讀
為什麼會看到廣告
avatar-img
6會員
5內容數
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
yuanchin的沙龍 的其他內容
為什麼要對任務進行排班呢?這篇文章將會告訴你,在作業系統當中,是如何利用排班演算法來處理交互式與非交互式任務,以及如何提升CPU使用率!
行程(進程、process)、執行緒(線程、thread)、上下文切換(context switch)、行程控制塊(PCB)、行程排班(process scheduler)、行程狀態、執行緒模式
Development environment of Laravel. Nginx, php, mysql and centos 7
為什麼要對任務進行排班呢?這篇文章將會告訴你,在作業系統當中,是如何利用排班演算法來處理交互式與非交互式任務,以及如何提升CPU使用率!
行程(進程、process)、執行緒(線程、thread)、上下文切換(context switch)、行程控制塊(PCB)、行程排班(process scheduler)、行程狀態、執行緒模式
Development environment of Laravel. Nginx, php, mysql and centos 7
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
避免 thread 競速(Race Condition)是多執行緒編程中常見的挑戰之一。 Race Condition 發生在多個執行緒同時訪問和修改共享資源時,因為執行緒之間的執行順序無法預測,可能會導致數據的不一致性或意外行為。 本文主要介紹如何使用Lock來避免此狀況出現。 首先先看沒
“所有人寫的程式會變成指令 每一道指令是由CPU執行 而CPU所能理解的指令類型有限”
Thumbnail
簡要說明 JavaScript 的 Event Loop JavaScript 是單執行緒 (single-threaded) 語言,這意味著它一次只能執行一件事,因此所有函式都需要排隊等待執行,這被稱為同步 (synchronous)。在同步操作中,若函式過多或過於複雜,會導致程式阻塞 (blo
※ 非同步概念總複習 為什麼要使用 Promise? 在 JavaScript 開發中,處理非同步操作是常見需求,涉及如文件讀寫、數據庫查詢或網路請求等耗時任務。傳統的回調方式可能導致代碼結構混亂,稱為「回調地獄」,難以維護和理解。 Promise 是解決這問題的方法。它是一個物件(objec
※ 同步概念: 單純地「由上而下」執行程式碼,而且一次只執行一件事,也就是「按順序執行,一個動作結束才能切換到下一個」。缺點是你需要「等待」事情執行完畢,才能繼續往下走。 ※ 非同步概念: 盡可能讓主要的執行程序不需要停下來等待,若遇到要等待的事情,就發起一個「非同步處理」,讓主程序繼續執行,
Thumbnail
在Python中,queue是一個非常有用的模块。 它提供了多種佇列(queue)實現,用於在多線程環境中安全地交換信息或者數據。 佇列(queue)是一種先進先出(FIFO)的數據結構,允許在佇列的一端插入元素,另一端取出元素。(FIFO 是First In, First Out 的縮寫)
Thumbnail
當你需要在 Python 中執行多個任務,但又不希望它們相互阻塞時,可以使用 threading 模組。 threading 模組允許你在單個程序中創建多個執行緒,這些執行緒可以同時運行,從而實現並行執行多個任務的效果。
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
為什麼需要非同步? 我們在「【Web微知識系列】 Web Workers」有介紹到在瀏覽器可執行腳本Javascript環境底下如何完成非同步的操作, 主要是為了讓任務更有效率的進行, 不會因為一個非常耗時的工作堵塞住整個服務, 導致無法服務他人的窘境。 大家應該經常在餐廳裡會看到服務員協
Thumbnail
關於多執行緒/多行程的使用方式 在Python 3.2版本之後加入了「concurrent.futures」啟動平行任務, 它可以更好的讓我們管理多執行緒/多行程的應用場景,讓我們在面對這種併發問題時可以不必害怕, 用一個非常簡單的方式就能夠處裡, 底下我們將為您展示一段程式碼: imp
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
避免 thread 競速(Race Condition)是多執行緒編程中常見的挑戰之一。 Race Condition 發生在多個執行緒同時訪問和修改共享資源時,因為執行緒之間的執行順序無法預測,可能會導致數據的不一致性或意外行為。 本文主要介紹如何使用Lock來避免此狀況出現。 首先先看沒
“所有人寫的程式會變成指令 每一道指令是由CPU執行 而CPU所能理解的指令類型有限”
Thumbnail
簡要說明 JavaScript 的 Event Loop JavaScript 是單執行緒 (single-threaded) 語言,這意味著它一次只能執行一件事,因此所有函式都需要排隊等待執行,這被稱為同步 (synchronous)。在同步操作中,若函式過多或過於複雜,會導致程式阻塞 (blo
※ 非同步概念總複習 為什麼要使用 Promise? 在 JavaScript 開發中,處理非同步操作是常見需求,涉及如文件讀寫、數據庫查詢或網路請求等耗時任務。傳統的回調方式可能導致代碼結構混亂,稱為「回調地獄」,難以維護和理解。 Promise 是解決這問題的方法。它是一個物件(objec
※ 同步概念: 單純地「由上而下」執行程式碼,而且一次只執行一件事,也就是「按順序執行,一個動作結束才能切換到下一個」。缺點是你需要「等待」事情執行完畢,才能繼續往下走。 ※ 非同步概念: 盡可能讓主要的執行程序不需要停下來等待,若遇到要等待的事情,就發起一個「非同步處理」,讓主程序繼續執行,
Thumbnail
在Python中,queue是一個非常有用的模块。 它提供了多種佇列(queue)實現,用於在多線程環境中安全地交換信息或者數據。 佇列(queue)是一種先進先出(FIFO)的數據結構,允許在佇列的一端插入元素,另一端取出元素。(FIFO 是First In, First Out 的縮寫)
Thumbnail
當你需要在 Python 中執行多個任務,但又不希望它們相互阻塞時,可以使用 threading 模組。 threading 模組允許你在單個程序中創建多個執行緒,這些執行緒可以同時運行,從而實現並行執行多個任務的效果。
Thumbnail
非同步程式設計(Asynchronous programming) 或是簡單的稱之為 async,它是一種並發程式模型(concurrent programming model),其目的就是讓多個任務能同時在作業系統的執行緒上執行,並透過 async/.await 保留同步。
Thumbnail
為什麼需要非同步? 我們在「【Web微知識系列】 Web Workers」有介紹到在瀏覽器可執行腳本Javascript環境底下如何完成非同步的操作, 主要是為了讓任務更有效率的進行, 不會因為一個非常耗時的工作堵塞住整個服務, 導致無法服務他人的窘境。 大家應該經常在餐廳裡會看到服務員協
Thumbnail
關於多執行緒/多行程的使用方式 在Python 3.2版本之後加入了「concurrent.futures」啟動平行任務, 它可以更好的讓我們管理多執行緒/多行程的應用場景,讓我們在面對這種併發問題時可以不必害怕, 用一個非常簡單的方式就能夠處裡, 底下我們將為您展示一段程式碼: imp