iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 21
3
Software Development

Golang入門到進階實戰系列 第 21

Day21 進程 線程與協程

進程process

定義

進程是程式執行的一個實例,擔當分配系統資源的實體,實程創建必須分配一個完整的獨立地址空間。它是操作系統動態執行的基本單元。

特徵

每個進程都有自己的記憶體空間,包含原始碼區域、數據區域、堆棧。進程是線性的容器,本身並不會運行,線程不能單獨存在,必須依賴進程。

一個程式至少有一個進程,一個進程至少有一個線程。

對於操作系統來說,一個任務就是一個進程,比如開一個瀏覽器就是啟動一個瀏覽器進程,打開一個app就是啟動一個app進程。一個進程不代表只有一個功能,例如在一個通訊app裡,其中擁有有打字通訊、語音通訊和傳檔案等許多功能。

進程狀態

  • 就緒:獲取出CPU外的所有資源、只要處理器分配資源就可以馬上執行
  • 運行:獲得處理器分配的資源,程序開始執行
  • 阻塞:當程序條件不夠的時候,需要等待提交滿足的時候才能執行。
  • 終止:進程結束,或是出現錯誤而被系統終止,進入終止狀態,無法再執行。

線程

線程是進程裡的執行者,一個進程中至少有一個線程。多線程是為了在單個程式中同時運行多個線程完成不同的任務或工作,不是為了提高運行效率,而是為了提高資源使用效率,進而提昇系統的效率。

線程是程序執行流的最小單元。一個標準的線程由當前的線程ID、當前指令指針、寄存器和堆棧組成。同一個進程中的多個線程之間可以並發執行。

線程狀態:

  • 就緒:指線程具備運行的所有條件,邏輯上可以運行,在等待處理機
  • 運行:指線程占用處理機正在運行
  • 阻塞:線程在等待一個事件,邏輯上不可執行

如果我們要同時執行多個任務怎麽辦?

我們有兩個選擇:

  1. 啟動多個進程,每個進程雖然只有一個線程,但是多個進程可以一塊執行多個任務
  2. 啟動一個進程,在一個進程內啟動多個線程,這樣多個線程也可以一塊執行多個任務

多個進程之間並不會共享資源,所以多進程會比多線程還需要更多的系統資源。多進程的好程是,假使其中一個進程發生錯誤被系統終止,其餘的進程也不會受到任何影響。

協程

協程是一種用戶態的輕量級線程,協程的調度完全由用戶控制(進程和線程都是由cpu 內核進行調度)。協程擁有自己的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢覆先前保存的寄存器上下文和棧,直接操作棧則基本沒有內核切換的開銷,可以不加鎖的訪問全局變量,所以上下文的切換非常快。

對於 進程、線程,都是有內核進行調度,有 CPU 時間片的概念,進行 搶占式調度(有多種調度算法)

對於 協程(用戶級線程),這是對內核透明的,也就是系統並不知道有協程的存在,是完全由用戶自己的程序進行調度的,因為是由用戶程序自己控制,那麽就很難像搶占式調度那樣做到強制的 CPU 控制權切換到其他進程/線程,通常只能進行 協作式調度,需要協程自己主動把控制權轉讓出去之後,其他協程才能被執行到。

使用協程的好處

協程有助於實現:

  • 狀態機:在一個子例程裡實現狀態機,這裡狀態由該過程當前的出口/入口點確定,可以產生可讀性更高的代碼。
  • 角色模型:並行的角色模型。
  • 產生器:有助於輸入/輸出和對數據結構的通過遍歷。

goroutine

普遍認為 goroutine 是Go語言對於協程的實現。 不同的是,Golang 在 runtime、系統調用等多方面對 goroutine 調度進行了封裝和處理,當遇到長時間執行或者進行系統調用時,會主動把當前 goroutine 的CPU (P) 轉讓出去,讓其他 goroutine 能被調度並執行,也就是 Golang 從語言層面支持了協程。Golang 的一大特色就是從語言層面原生支持協程,在函數或者方法前面加 go關鍵字就可創建一個協程。

與線程的比較

記憶體

每個 goroutine (協程) 默認占用記憶體遠比 Java 、C 的線程少。
goroutine:2KB(官方)
線程:8MB(參考網絡)

切換調度

線程/goroutine 切換開銷方面,goroutine 遠比線程小
線程:涉及模式切換(從用戶態切換到內核態)、16個寄存器、PC、SP...等寄存器的刷新等。
goroutine:只有三個寄存器的值修改 - PC / SP / DX.


上一篇
Day20 Concurrency vs Parallelism
下一篇
Day22 競爭條件Race Condition
系列文
Golang入門到進階實戰30

尚未有邦友留言

立即登入留言