go是多線程還是協程?
3.1 概念
在go程序中,由輕量級線程實現,由Go運行時(runtime)管理。
3.2 與進程、線程的區別
1)進程擁有自己獨立的堆棧,既不共享堆,也不共享棧。是由操作系統調度的。
2)線程擁有自己獨立的棧和共享的堆,共享堆,不共享棧,是由操作系統調度。
2)協程共享堆,不共享棧,協程是由程序員在協程的代碼中顯示調度。
3.3 主線程和協程的關系
3.4 協程比線程輕量的原因
3.4.1 線程并發的流程
線程是內核對外提供的服務,應用程序可以通過系統調用讓內核啟動線程,由內核來負責線程的調度和切換。線程在等待I/O操作時線程變為unrunnable狀態會觸發上下文切換。現代操作系統一般都采用搶占式調度,上下文切換一般發生在時鐘中斷和系統調用返回前,調度器計算當前線程的時間片,如果需要切換就從隊列中選出一個目標線程,保存當前線程的環境,并且恢復目標線程的運行環境,最典型的就是切換ESP指向目標線程內核堆棧,將EIP指向目標線程上次被調度出時的指令地址。
3.4.2 協程并發的流程
不依賴操作系統和其提供的線程,golang自己實現的CSP并發模型:M,P,G
go協程也叫用戶態線程,協程之間的切換發生在用戶態。在用戶態沒有時鐘中斷、系統調用等機制,因此效率高。
3.5 go協程占用內存少的原因
執行go協程只需要極少的棧內存(大概4~5KB),默認情況下,線程棧的大小為1MB。
goroutine就是一段代碼,一個函數入口,以及在堆上分配的一個堆棧。所以我們可以輕松創建上萬個goroutine,但他們并不是被操作系統調度執行的。