Go的CSP併發模型

Go實現了兩種併發形式。第一種是大家普遍認知的:多線程共享內存。其實就是Java或者C++等語言中的多線程開發。另外一種是Go語言特有的,也是Go語言推薦的:CSP(communicating sequential processes)併發模型。

CSPCommunicating Sequential Process 的簡稱,中文可以叫做通信順序進程,是一種併發編程模型,由 Tony Hoare 於 1977 年提出。簡單來說,CSP 模型由併發執行的實體(線程或者進程)所組成,實體之間通過發送消息進行通信,這裏發送消息時使用的就是通道,或者叫 channel。CSP 模型的關鍵是關注 channel,而不關注發送消息的實體。Go 語言實現了 CSP 部分理論。

請記住下面這句話:

Do not communicate by sharing memory; instead, share memory by communicating.
“不要以共享內存的方式來通信,相反,要通過通信來共享內存。”

普通的線程併發模型,就是像Java、C++、或者Python,他們線程間通信都是通過共享內存的方式來進行的。非常典型的方式就是,在訪問共享數據(例如數組、Map、或者某個結構體或對象)的時候,通過鎖來訪問,因此,在很多時候,衍生出一種方便操作的數據結構,叫做“線程安全的數據結構”。例如Java提供的包”java.util.concurrent”中的數據結構。Go中也實現了傳統的線程併發模型。

Go的CSP併發模型,是通過goroutine和channel來實現的。

goroutine 是Go語言中併發的執行單位。其實就是協程,參考我之前寫的 用大白話講進程和線程、協程的區別 - 簡書

channel是Go語言中各個併發結構體(goroutine)之前的通信機制。 通俗的講,就是各個goroutine之間通信的”管道“,有點類似於Linux中的管道。

Channel

Golang中使用 CSP中 channel 這個概念。channel 是被單獨創建並且可以在進程之間傳遞,它的通信模式類似於 boss-worker 模式的,一個實體通過將消息發送到channel 中,然後又監聽這個 channel 的實體處理,兩個實體之間是匿名的,這個就實現實體中間的解耦,其中 channel 是同步的一個消息被髮送到 channel 中,最終是一定要被另外的實體消費掉的。

Goroutine

Goroutine 是實際併發執行的實體,它底層是使用協程(coroutine)實現併發,coroutine是一種運行在用戶態的用戶線程,類似於 greenthread,go底層選擇使用coroutine的出發點是因爲,它具有以下特點:

  1. 用戶空間 避免了內核態和用戶態的切換導致的成本
  2. 可以由語言和框架層進行調度
  3. 更小的棧空間允許創建大量的實例
  4. 用戶空間線程的調度不是由操作系統來完成的,像在java 1.3中使用的greenthread的是由JVM統一調度的(後java已經改爲內核線程),還有在ruby中的fiber(半協程) 是需要在重新中自己進行調度的,而goroutine是在golang層面提供了調度器,並且對網絡IO庫進行了封裝,屏蔽了複雜的細節,對外提供統一的語法關鍵字支持,簡化了併發程序編寫的成本。

作者:碼農甲
鏈接:https://www.jianshu.com/p/a3c9a05466e1
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章