協程(CoRoutine)是一種輕量級的使用者態執行緒。簡單來說,執行緒(thread)的排程是由作業系統負責,執行緒的睡眠、等待、喚醒的時機是由作業系統控制,開發者無法決定。使用協程,開發者可以自行控制程式切換的時機,可以在一個函式執行到一半的時候中斷執行,讓出CPU,在需要的時候再回到中斷點繼續執行。因為切換的時機是由開發者來決定的,就可以結合業務的需求來實現一些高階的特性。
協程的特點:
有獨立的棧空間
共享程式堆空間
排程由使用者控制
協程是輕量級的執行緒
協程的優點:
程式碼編輯簡單。可以將非同步處理邏輯程式碼用同步的方式編寫,將多個非同步操作集中到一個函式中完成。
單執行緒模式,沒有執行緒安全的問題,不需要加鎖操作。
效能好。協程是使用者態執行緒,切換更加高效。
為什麼協程比執行緒輕量?
一旦建立完執行緒,你就無法決定他什麼時候獲得時間片,什麼時候讓出時間片了,你把它交給了核心。而協程編寫者可以有:可控的切換時機和很小的切換代價。從作業系統有沒有排程權上看,協程就是因為不需要進行核心態的切換。
go協程呼叫跟切換比執行緒效率高
執行緒併發執行流程:
執行緒是核心對外提供的服務,應用程式可以透過系統呼叫讓核心啟動執行緒,由核心來負責執行緒排程和切換。執行緒在等待IO操作時執行緒變為unrunnable狀態會觸發上下文切換。現代作業系統一般都採用搶佔式排程,上下文切換一般發生在時鐘中斷和系統呼叫返回前,排程器計算當前執行緒的時間片,如果需要切換就從執行佇列中選出一個目標執行緒,儲存當前執行緒的環境,並且恢復目標執行緒的執行環境,最典型的就是切換ESP指向目標執行緒核心堆疊,將EIP指向目標執行緒上次被排程出時的指令地址。
go協程併發執行流程:
不依賴作業系統和其提供的執行緒,golang自己實現的CSP併發模型實現:M, P, G。
go協程也叫使用者態執行緒,協程之間的切換髮生在使用者態。在使用者態沒有時鐘中斷,系統呼叫等機制,因此效率高。
go協程佔用記憶體少
執行go協程只需要極少的棧記憶體(最新版預設2KB,可以根據程式執行自動伸縮),預設情況下,執行緒棧的大小為1MB。
goroutine就是一段程式碼,一個函式入口,以及在堆上為其分配的一個堆疊。所以它非常廉價,我們可以很輕鬆的建立上萬個goroutine,但它們並不是被作業系統所排程執行。