對程式、執行緒和協程的理解以及它們的區別

九卷發表於2022-04-26

一、程式

先來了解一下作業系統的程式:

作業系統對正在執行程式的抽象,這個就是程式(process)。

比如執行一個 web 瀏覽器,一個 text 文字,都是執行的一個一個程式。

有的人說:程式是程式執行資源的集合。程式是系統資源分配的最小單位等等。

從靜態的角度來說,程式確實是執行程式的各種資源集合。

如果你進一步思考,程式裡的各種資源都有哪些呢?如下圖所示:

image-20220425233252807

​ (圖1:程式資源)

  • 記憶體管理相關

  • 檔案系統

  • 排程相關

  • 訊號處理

  • 核心棧

  • 程式各種狀態

  • 程式執行時統計資訊

  • 程式標識

等等。

可以看出,程式中的資源是相當多的。

從 Linux 作業系統對程式的定義也可以看出。我以前對程式結構 task_struct 分析文章:Linux程式: task_struct結構體成員

多程式:作業系統有多個程式執行,那麼就有多個程式,如下所示簡圖:

image-20220425183626070

​ (圖2:多程式簡圖)

二、執行緒

2.1 什麼是執行緒?

《作業系統設計與實現》裡說:

在傳統作業系統中,每個程式中只存在一個地址空間和一個控制流(thread)。

然後,有些情況下,需要在相同地址空間中有多個控制流並行的執行,就像他們是單獨的程式一樣(只是他們共享相同的地址空間)。

這些控制流通常被稱為執行緒(thread),有時也稱為輕量級程式(lightweight process)。

儘管執行緒必須在程式中執行,但是執行緒和程式是可以分別對待處理的兩個概念。程式用來集合資源,而執行緒是 CPU 排程的實體。

執行緒給程式模型增加的是,允許在同一個程式環境中有多個執行流,這些執行流在很大程度上相對獨立。

也即是說,在程式中,程式執行的最小單位(執行流)是執行緒,可以把執行緒看作是程式裡的一條執行流。

一個程式裡可以有一條或多條執行緒。

image-20220425204853673

​ (圖3:程式裡的執行緒)

2.2 為什麼會有多執行緒?

在一個應用程式執行過程中,應用程式裡可能會有多種事件執行。

而有些事件執行一段時間後可能會被阻塞。如果把應用程式執行事件分解成多個並行執行的執行緒,即可以讓程式設計變得簡單,如果有阻塞的,

可以把這部分讓出行換其他執行緒執行。

還有一個原因是:

執行緒比程式更輕量級。所以執行緒比程式更加容易建立,銷燬。

第三個跟第一個有點關係,是關於效能的,若多執行緒都是 CPU 密集型的,那麼不能獲取效能上增強。如果有大量計算和大量 I/O 處理,那麼

多執行緒就可以獲取效能上的優勢,因為允許多執行緒重疊執行。

多執行緒的缺點:

  1. 對於多執行緒來說,程式中的資源是共享的,所以會產生資源競爭。
  2. 當程式中的一個執行緒崩潰了,會導致這個程式裡的其他執行緒也崩潰。所以有時多程式程式更好,一個程式崩潰不會導致其他程式也崩潰。

三、程式與執行緒區別

從上面程式和執行緒介紹知道,執行緒是程式執行流的最小單位,程式是作業系統分配資源的單位。

程式與程式之間關係:

程式與程式之間是相互獨立的。

執行緒與程式關係:

執行緒是程式裡的執行流,程式裡的執行緒可以是一個,也可以是多個。

所有執行緒共享程式裡一些資源,比如程式碼,資料,地址空間,訊號處理,開啟檔案,全域性變數等。

同時,執行緒也有自己的暫存器,程式計數器,堆疊,執行緒狀態等

image-20220425233616408

​ (圖4:程式與執行緒關係)

四、協程

協程是建立線上程之上,一般是語言級別的 ”多執行緒“ 模型,比執行緒更加的輕量級。有的叫它微執行緒。它是完全執行在使用者態裡。

協程是線上程之上在進行抽象,它需要執行緒來承載執行。一個執行緒可以執行多個協程。

比如 Go 語言的 goroutine,它用一個關鍵字 go 就可以執行一個協程程式。

在 Go 語言裡面,協程是由 Go 提供的 runtime 來控制和排程。

協程的優點:

  1. 協程棧很小,只有幾KB,而執行緒棧是 1 M,對比起來,建立大量協程需要的記憶體更少。

  2. 協程的排程是語言提供的 runtime 來排程,是在使用者空間直接排程,不需要在核心空間和使用者空間來回切換,浪費效率。

  3. 能更好的利用 cpu 的多核,提高程式執行效能。

  4. 避免阻塞,如果協程所在的執行緒發生了阻塞,那麼協程排程器可以把執行在阻塞執行緒上的協程,排程到其它沒有發生阻塞的執行緒上,繼續執行。

五:協程與執行緒區別

  1. 協程是執行線上程之上,一個執行緒可以執行多個協程。就像一個程式裡可以有多個執行緒一樣。
  2. 協程能更好的利用多核機制。比如 Go 協程可以控制執行在多少個 CPU 的核上。
  3. 協程是在使用者空間完成排程,由語言提供的 runtime 進行排程完全使用者態。執行緒由核心排程。
  4. 協程使用記憶體更小。

六、參考

相關文章