Goroutine 淺析

首發于:https://zhuanlan.zhihu.com/p/22297799?refer=lihang

并發還是并行

Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once.[1]

并發的目的在于把當個 CPU 的利用率使用到最高。并行則需要多核 CPU 的支持。

CSP

Communicating Sequential Processes,譯為通信順序進程。是一種形式語言,用來描述并發系統間進行交互的模式。
例如:

COPY = *[c:character; west?c → east!c]
the process repeatedly receives a character from the process named west, and then sends that character to process named east. The parallel composition

[west::DISASSEMBLE || X::COPY || east::ASSEMBLE]
assigns the names west to the DISASSEMBLE process, X to the COPY process, and east to the ASSEMBLE process, and executes these three processes concurrently.[3]

CSP 通過把輸入/輸出和并發環境下的進程通信作為基礎的方法和結構。定義了一套自己的原語,包括:并發執行,輸入/輸出,循環執行,條件判斷等。然后用定義好的語法去實現一些常見的問題,比如:協程,數論,經典的同步問題(生產者消費者,哲學家就餐)。

通過 CSP 的定義,使并發編程能在更高的層次實現,編寫的程序不需要關心底層的資源共享、加鎖、調度切換等細節,使并發程序的編寫更簡單。[6]

Go 就是基于 CSP 的思想來實現的并發模型。

Go runtime scheduler

Why need Go scheduler?

主要有兩個原因:

  • 線程較多時,開銷較大。
  • OS 的調度,程序不可控。而 Go GC 需要停止所有的線程,使內存達到一致狀態。[7]

Struct

M 代表系統線程,G 代表 goroutine,P 代表 context。

M:N

There are 3 usual models for threading. One is N:1 where several userspace threads are run on one OS thread. This has the advantage of being very quick to context switch but cannot take advantage of multi-core systems. Another is 1:1 where one thread of execution matches one OS thread. It takes advantage of all of the cores on the machine, but context switching is slow because it has to trap through the OS.[7]

M:N 則綜合兩種方式(N:1, 1:1)的優勢。多個 goroutines 可以在多個 OS threads 上處理。既能快速切換上下文,也能利用多核的優勢。

Context switch

在程序中任何對系統 API 的調用,都會被 runtime 層攔截來方便調度。
Goroutine 在 system call 和 channel call 時都可能發生阻塞[8],但這兩種阻塞發生后,處理方式又不一樣的。

  • 當程序發生 system call,M 會發生阻塞,同時喚起(或創建)一個新的 M 繼續執行其他的 G。

If the Go code requires the M to block, for instance by invoking a system call, then another M will be woken up from the global queue of idle M’s. This is done to ensure that goroutines, still capable of running, are not blocked from running by the lack of an available M.[11]

  • 當程序發起一個 channel call,程序可能會阻塞,但不會阻塞 M,G 的狀態會設置為 waiting,M 繼續執行其他的 G。當 G 的調用完成,會有一個可用的 M 繼續執行它。

If a goroutine makes a channel call, it may need to block, but there is no reason that the M running that G should be forced to block as well. In a case such as this, the G’s status is set to waiting and the M that was previously running it continues running other G’s until the channel communication is complete. At that point the G’s status is set back to runnable and will be run as soon as there is an M capable of running it.[11]

P 的作用:

  • 每個 P 都有一個隊列,用來存正在執行的 G。避免 Global Sched Lock。
  • 每個 M 運行都需要一個 MCache 結構。M Pool 中通常有較多 M,但執行的只有幾個,為每個池子中的每個 M 分配一個 MCache 則會形成不必要的浪費,通過把 cache 從 M 移到 P,每個運行的 M 都有關聯的 P,這樣只有運行的 M 才有自己的 MCache。[11]

Goroutine vs OS thread

其實 goroutine 用到的就是線程池的技術,當 goroutine 需要執行時,會從 thread pool 中選出一個可用的 M 或者新建一個 M。而 thread pool 中如何選取線程,擴建線程,回收線程,Go Scheduler 進行了封裝,對程序透明,只管調用就行,從而簡化了 thread pool 的使用。[12]

Goroutine vs Python yield

  • 創建成本:Go 原生支持協程,通過 go func() 就可以創建一個 goroutine。Python 可以通過 gevent.spawn 來新建一個 coroutine,需要第三方庫來支持。
  • Goroutine 之間的通信更簡單,通過 channel call 即可實現,上下文切換透明(只有少部分需要自己注意 Gosched)。Python 需要 yield 來傳遞數據和切換上下文(通過一些庫封裝后對調用者來說也是透明的,比如:gevent/tornado)。
  • Python coroutine 只會使用一個線程,所以只能利用單核。Goroutine 可以被多個線程調度,可以利用多核。

References:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容

  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,769評論 0 23
  • 十月初一,冬天的第一天,氣候漸漸寒冷,人們怕在冥間的祖先缺衣少穿,因此,祭祀衣食用品。在祭祀時,人們把寒衣焚化給祖...
    7默閱讀 575評論 1 0
  • 社交圈在哪里,就在你的生活里,把你自己想象為一個圓心,半徑100米的地方就是你的社交圈,意中人就將會出現在這些社交...
    而我想成為一個陽光女孩閱讀 2,342評論 1 16
  • 春天來的時候,總覺得會發生點什么。 一半在土里安詳,一半在風里飛揚, 一半灑落陰涼,一半沐浴陽光。 昨天還是漫山遍...
    璞玉57閱讀 232評論 0 1