首頁  >  文章  >  後端開發  >  golang中執行緒和協程的差別是什麼

golang中執行緒和協程的差別是什麼

青灯夜游
青灯夜游原創
2021-03-18 17:23:553162瀏覽

區別:線程中資料儲存在內核狀態的記憶體空間;而協程中資料儲存在執行緒提供的用戶狀態記憶體空間。執行緒的任務調度由核心實現,搶佔方式,依賴各種鎖;協程的任務調度由用戶態實現的具體調度器進行。

golang中執行緒和協程的差別是什麼

本教學操作環境:windows10系統、GO 1.11.2、thinkpad t480電腦。

協程
協程,英文名Coroutine。但在 Go 語言中,協程的英文名是:gorutine。它常常被用於進行多任務,即並發作業。沒錯,就是多執行緒作業的那個作業。

雖然在 Go 中,我們不用直接寫線程之類的程式碼來進行並發,但是 Go 的協程卻依賴線程來進行。

下面我們來看看它們的差異。

線程的基礎介紹,這裡請自行上網搜尋文章,因為關於線程的優秀介紹文章已經很多。

協程的特點
這裡先直接列出執行緒的特點,然後再從例子中解析。

  • 多個協程可由一個或多個執行緒管理,協程的調度發生在其所在的執行緒中。

  • 可以被調度,調度策略由應用層程式碼定義,即可被高度自訂實作。

  • 執行效率高。

  • 佔用記憶體少。

上面第1第2

我们来看一个例子:
func TestGorutine(t *testing.T) {
	runtime.GOMAXPROCS(1)  // 指定最大 P 为 1,从而管理协程最多的线程为 1 个
	wg := sync.WaitGroup{} // 控制等待所有协程都执行完再退出程序
	wg.Add(2)
	// 运行一个协程
	go func() {
		fmt.Println(1)
		fmt.Println(2)
		fmt.Println(3)
		wg.Done()
	}()

	// 运行第二个协程
	go func() {
		fmt.Println(65)
		fmt.Println(66)
		// 设置个睡眠,让该协程执行超时而被挂起,引起超时调度
		time.Sleep(time.Second)
		fmt.Println(67)
		wg.Done()
	}()
	wg.Wait()}

上面的程式碼片段跑了兩個協程,運行後,觀察輸出的順序是交錯的。可能是:

656612367

意味著在執行協程A的過程中,可以隨時中斷,去執協程行B,協程B也可能在執行過程中中斷再去執行協程A。
看起來協程A 和 協程B 的運行像是執行緒的切換,但請注意,這裡的 A 和 B都運行在同一個執行緒裡面。它們的調度不是線程的切換,而是純應用程式的協程調度
關於上述程式碼中,為什麼要指定下面兩行程式碼?

runtime.GOMAXPROCS(1)time.Sleep(time.Second)

這需要您去看下Go 的協程調度入門基礎,請看我之前的另外一篇調度分析文章:
Go 的協程調度機制

如果不設定runtime.GOMAXPROCS(1),那麼程式將會根據作業系統的CPU 核數而啟動對應數量的P,導致多個M,即執行緒的啟動。那麼我們程式中的協程,就會被分配到不同的執行緒裡面去了。為了演示,故設定數量 1,使得它們都被分配到了同一個線程裡面,存於線程的協程隊列裡面,等待被執行或調度。

協程特點中的第 3第 4點。
3. 執行效率高。
4. 佔用記憶體少。

因為協程的調度切換不是執行緒切換,而是由程式本身控制,因此,沒有執行緒切換的開銷,和多執行緒比,執行緒數量越多,協程的性能優勢就越明顯。調度發生在應用態而非內核態。

內存的花銷,使用其所在的線程的內存,意味著線程的內存可以供多個協程使用。

其次協程的調度不需要多線程的鎖定機制,因為只有一個線程,也不存在同時寫變數衝突,所以執行效率比多線程高很多。

協程與執行緒的整體比較

#比較的點 執行緒 #協程
資料儲存 核心狀態的記憶體空間 一般是執行緒提供的使用者狀態記憶體空間
切換操作 操作最終在核心層完成,應用層需要呼叫核心層提供的syscall 底層函數 應用層使用程式碼進行簡單的現場保存和恢復即可
任務調度 由內核實現,搶佔方式,依賴各種鎖 由用戶態的實現的具體調度器進行。例如go 協程的調度器
語音支援程度 絕大部分程式語言 部分語言:Lua,Go,Python …
實作規格 依照現代作業系統規格實作 無統一規範。在應用層由開發者實現,高度自訂,例如只支援單執行緒的執行緒。不同的調度策略,等等

推薦學習:Golang教學

以上是golang中執行緒和協程的差別是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
上一篇:golang有指針嗎下一篇:golang有指針嗎