區別:1、執行緒是程式執行的最小單位,而程序是作業系統分配資源的最小單位。2、一個程序由一個或多個執行緒組成,執行緒是一個程序中程式碼的不同執行路線。3、執行緒上下文切換比程序上下文切換要快得多。4、程序切換需要的資源很最大,效率很低;執行緒切換需要的資源一般,效率一般。5、程序擁有自己的堆疊,程序之間不共用堆疊;執行緒擁有自己的棧,共用堆。
本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。
程序
大部分作業系統(Windows、Linux)的任務排程採用時間片輪轉的搶佔式排程方式。
該排程方式如下:
在一個程序中,當一個執行緒任務執行幾毫秒後,會由作業系統核心進行排程
通過硬體的計數器中斷處理器,讓該執行緒強制暫停並將該執行緒的暫存器放入記憶體中
通過檢視執行緒列表決定接下來執行哪一個執行緒
然後從記憶體中恢復該執行緒的暫存器,最後恢復該執行緒的執行,從而去執行下一個任務
這種方式保證了每個執行緒輪流執行,由於CPU的執行效率非常高,時間片非常短,在各個任務之間快速地切換,給人的感覺就是多個任務在同時進行,這就是我們說的並行。
執行緒是程式執行的最小單位,而程序是作業系統分配資源的最小單位
一個程序由一個或多個執行緒組成,執行緒是一個程序中程式碼的不同執行路線
執行緒上下文切換比程序上下文切換要快得多
程序切換需要的資源很最大,效率很低;執行緒切換需要的資源一般,效率一般。
程序擁有自己的堆疊,程序之間不共用堆疊,由作業系統排程
執行緒擁有自己的棧,共用堆,也是由作業系統排程
多核處理器是指在一個處理器上整合了多個運算核心從而提高計算能力。也就是有多個真正平行計算的處理核心,每一個處理核心對應一個核心執行緒。
每一個處理核心對應一個核心執行緒。
比如:
核心執行緒(Kernel Thread,KLT)就是直接由作業系統核心支援的執行緒。該執行緒由核心來完成執行緒切換,核心通過操作排程器對執行緒進行排程,並負責將執行緒的任務對映到各個處理器上。
目前處理器都採用了超執行緒技術將一個 物理處理核心模擬成兩個邏輯處理核心,也就是兩個核心執行緒。
所以我們看到的電腦一般都是雙核四執行緒、四核八執行緒。
在作業系統中我們看到CPU數量是實際物理CPU數量的兩倍,如雙核四執行緒可以看到4CPU。
如我當前編寫文章的這臺mbp就是i7 6核12執行緒:
程式一般不會直接使用核心執行緒,而是使用核心執行緒的一種高階介面—輕量級程序(Lightweight Process,LWP),也就是我們常說的執行緒。
協程(Coroutines)基於執行緒之上,比執行緒更加輕量級。一個執行緒可以擁有多個協程。
傳統應用中一般有會給網路請求建立一個執行緒去完成業務邏輯。如果是多個請求,就會建立多個執行緒來出來。
如果遇到很耗時的I/O行為,執行緒就會一直處於阻塞狀態,如果很多執行緒都是出於這種空閒狀態(等待該執行緒執行完成才能執行),這樣就會造成資源應用不徹底,系統的吞吐能力下降。
最常見的很耗時的I/O行為比如JDBC,CPU會一直等待資料I/O操作的返回,這時執行緒根本沒有利用CPU去做運算,而是處於空閒狀態。同時使用過多的執行緒,也會帶來更多的上下文切換開銷。
解決上述問題有兩個方案:
協程的流程:
當出現I/O阻塞的時候,由協程的排程器進行排程
通過將資料流立刻yield掉(主動讓出),並記錄當前棧上的資料
阻塞完成後立刻在通過執行緒恢復棧,並把阻塞的結果放到這個執行緒上去跑
而跑在由Coroutine
負責排程的執行緒稱為Fiber
,比如Golang裡的go
關鍵字其實就是負責開啟一個Fiber
,讓func
邏輯跑在上面。
由於協程的暫停完全由程式控制,發生在使用者態上;而執行緒的阻塞狀態是由作業系統核心來進行切換,發生在核心態上。
因此協程的開銷遠遠小於執行緒,也就沒有上下文切換的開銷。
比較項 | 執行緒 | 協程 |
---|---|---|
佔用資源 | 初始單位為1MB,固定不可變 | 初始一般為2KB,可隨需要增大 |
排程所屬 | 有OS核心完成 | 由使用者完成 |
切換開銷 | 設計模式切換(從使用者態切換到核心態),16個暫存器、PC、SP等暫存器的重新整理 | 只有三個暫存器的值修改:PC、SP、DX |
效能問題 | 資源佔用太高,頻繁建立銷燬會帶來嚴重的效能問題 | 資源佔用小,不會帶來嚴重的效能問題 |
資料同步 | 需要鎖等機制確保資料的一致性和可見性 | 不需要多執行緒的鎖機制,因此只有一個執行緒。也不存在同時寫變數衝突,在協程中控制共用資源不加鎖,只需要判斷狀態就好了,所以執行效率比執行緒高很多 |
【相關推薦:Go視訊教學、】
以上就是go語言中執行緒和程序的區別是什麼的詳細內容,更多請關注TW511.COM其它相關文章!