一.進程、線程、協程介紹
進程:系統中所有的應用程序都是以進程(process)的方式運行,是系統進行資源分配和調度的基本單位,每個進程都有自己的獨立的地址空間,使得進程之間的地址空間相互隔離。
線程:線程是程序執行流的最小單元上,通常意義上,一個進程由一個到多個線程組成,各個線程之間共享程序的內存空間(包括代碼段、數據段、堆等)及一些進程級的資源(如打開的文件和信號)。
協程:協程在Go語言中,由輕量級線程實現,由Go運行時(runtime)管理。
這里特別說明下並發和並行:
- 並發:多線程程序在單核上運行
- 並行:多線程程序在多核上運行
二.協程與進程、線程的區別
1)進程擁有自己的堆棧,不共享堆和棧,是由操作系統進行調度的。
2)線程擁有自己的獨立的棧和共享的堆,也是由操作系統進行調度。
3)協程共享堆,不共享棧,協程的調度由用戶控制。
三.協程的優點
1)代碼編輯簡單,可以將異步處理邏輯代碼用同步的方式編寫,將多個異步操作集中到一個函數中完成。
2)單線程模式,沒有線程安全的問題,不需要加鎖操作。
3)性能好,協程是用戶態線程,切換更加高效。
四.協程比線程輕量分析
一旦我們創建完線程,就無法決定它什么時候獲得時間片,什么時候讓出時間片,這里都交給了內核。和我們編寫協程時可以控制,可控的切換時機和很小的切換代價,從操作系統有沒有調度權來看,協程就是因為不需要進行內核態的切換。
1)Go協程調用跟切換比線程效率高
線程並發執行流程:
線程是內核對外提供的服務,應用程序可以通過系統調用讓內核啟動線程,由內核來負責線程調度和切換,線程在等待IO操作時標為unrunnable狀態會觸發上下文切換。現代操作系統一般采用搶占式調度,上下文切換一般發生在時鍾中斷和系統調用返回前,調度器計算當前線程的時間片,如果需要切換就從運行隊列中選出一個目標線程,保存當前線程的環境,並且恢復目標線程的運行環境,最典型的就是切換ESP指向目標線程內核堆棧,將EIP指向目標線程上次被調度出時的指令地址。
Go協程並發執行流程:
不依賴操作系統和其提供的線程,Golang自己實現的CSP並發模型實現:M,P,G
Go協程也叫用戶態線程,協程之間的切換發生在用戶態,在用戶態沒有時鍾中斷,系統調用等機制,因此效率高。
2)Go協程占用內存小
執行Go協程只需要極少的棧內存(大概4~5KB),默認情況下,線程棧的大小為1MB。
Goroutine就是一段代碼,一個函數入口,以及在堆上為其分配的一個堆棧,所以它非常廉價,我們可以很輕松的創建上萬個Goroutine,但它們並不是被操作系統所調度執行。