《Go 語言併發之道》讀後感 - 第二章
Go 語言併發之道讀後感-第二章
CSP (Communicating Sequential Processes) 我們可能聽說過,通過通訊去共享記憶體,Go pipeline 等,這一切的核心思想就是 CSP 理論。在這一章作者詳盡的介紹了 CSP 與 Go 併發哲學的關係。
併發與並行的區別
併發屬於程式碼,並行屬於一個執行中的程式。
引用 Erlang 之父 Joe Armstrong 圖
併發 = 兩個佇列一個咖啡機,兩個佇列的人交替使用咖啡機,可能會遇見如下情況:
A 佇列被 B 佇列小夥伴插隊了,這就是條件競爭。
A 佇列有一位英俊小夥和 B 佇列一位女神並排,輪到他們倆的時候兩人互看對方一眼,互讓一步同時彬彬有禮的說了一句:你先。這個時候活鎖出現了。
B 佇列一位小夥伴,是代替其他朋友來打咖啡,他帶了一箱子杯子,終於輪到他了。這時飢餓就出現了。
A 佇列一位小夥伴喜歡摩卡,卡布奇諾混合咖啡,B 佇列一位小夥伴喜歡拿鐵,摩卡混合咖啡。當他們互相等待對方摩卡出杯的時候後,死鎖來了。
並行 = 兩個佇列兩臺咖啡機。
編寫正確的併發邏輯越難,越需要我們將很簡單的併發原語組合起來使用。在 Go 語言出現之前,大部分的主流變成語言都有一系列的抽象層。 如果你想寫併發程式碼,你需要對你的程式按照執行緒同步以及記憶體訪問同步來建模。如果你又一大堆需要併發建模的東西,而你的計算機又不能處理那麼多的執行緒,就需要建立一個執行緒池並將你的操作線上程池中複用。
Go 語言在這個聯調中加入了新的一環:goroutine。另外,Go 語言從著名的電腦科學家 Tony Hoare 那裡借用了不少概念,並且給我們提供了新的原語來使用,即 channel。Go 語言併發原語的根基論文: Tony Hoare 開創性的論文 “Communicating Sequential Processes”。
在 Go 語言中執行緒依舊存在,但是已經不需要我們去操心執行緒建立,複用,銷燬,合併等操作,由 Go 語言本身完成。我們只需要使用更加簡單的 goroutine 和 channel 角度。偶爾需要考慮一下共享記憶體的問題。
什麼是 CSP
當進行和 Go 語言相關的討論的時候,你經常會聽到人們丟擲 CSP 縮寫。
CSP 即 “Communicating Sequential Processes" 的縮寫,譯為通訊順序京城。在 1978 年,Richard Hoare 在國際計算機協會工作時發表的論文。
在這篇論文裡,Hoare 認為輸入與輸出時兩個被忽略的程式設計原語,尤其是在併發程式碼中。在 Hoare 寫作這篇論文的同時,物件導向反省正在成為程式設計的基石,併發操作並沒有被給與過多的思考。Hoare 開始糾正這個現象,在接下來的 6 年裡,關於 CSP 的想法被提煉成了一個叫做 "程式微積分"的正式名稱來將 CSP 的想法投入到併發程式設計實踐中。
一個程式的輸出應該直接流量另一個程式的輸入。一個由守護的命令僅僅是一個帶有左和右傾向的語句,由→來分隔。左側服務是有執行條件的,或者是守護右側服務,如果左側服務執行失敗,或者在一個命令執行後,返回 false 或者退出,右側服務永遠不會被執行。將這些與 Hoare 的思想組合機器,為 Hoare 通訊過程奠定了基礎,從而實現了 channel。
Go 如何幫助你
goroutine 把我們從必須按照並行的方式思考中解放出來,作為替代,它准許我們按照更為自然的等級對問題進行建模。
channel 幫助我們把每一個 goroutine 組合在一起。
select 語句是對 channel 的一個補充,並且是多個 channel 組合的所有難點得以實現。
這裡我推薦劉丹冰的 GMP 講解:
https://zhuanlan.zhihu.com/p/168610624
Go 語言的併發哲學
“使用同行來共享記憶體,而不是是通過共享記憶體來通訊 “ ,這句座右銘想必麼一個 Gopher 都熟知。在併發程式碼編寫中 Go 提供了併發原語 (go,channel) 和 sync 包供我們選擇,那麼我們什麼時候應該選擇併發原語,什麼時候選擇記憶體訪問同步呢?以下這副圖給出了答案:
你是否需要轉讓資料所有權?
如果需要將計算結果給你共享給其他的程式碼塊,那麼你應該選擇 channel。這樣做有兩個好處:
- 建立一個帶有快取的 channel 來實現一個低成本的在記憶體中的佇列來解耦你的生產者和消費者
- channel 確保你的併發程式碼可以和其他併發程式碼進行組合
你是否檢視在保護某個資料結構的內部狀態?
當你需要保護某一個資料結構的時候這事原子操作,臨界區進入最小狀態,我們需要將這個行為鎖起來。所以這時使用 sync 包
你是否試圖協調多個邏輯片段?
記住,channel 比記憶體同步原語更具有可組合性。Go 團隊鼓勵漫天飛的 channel ,如果滿篇鎖對於任何語言可能都是災難。
這是一個效能要求很高的臨界區嗎?
channel 使用做記憶體訪問同步來操作,因此它只能更慢。
追求簡潔,儘量使用 channel ,並且認為 goroutine 的使用是沒有成本的。
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 《Go 語言併發之道》讀後感 - 第一章Go
- 《Go 語言併發之道》讀後感 - 第三章Go
- 《Go 語言併發之道》讀後感 - 第四章Go
- GO語言併發Go
- 《七週七語言》讀後感
- 第09章 Go語言併發,Golang併發Golang
- Go語言併發程式設計Go程式設計
- Go 語言的組合之道Go
- 十九、Go語言基礎之併發Go
- 《C語言入門經典》讀後感(一)C語言
- Java併發程式設計實戰——讀後感Java程式設計
- LINUX核心修煉之道–讀後感薦Linux
- Go語言是徹底的面向組合的併發語言Go
- 【資源分享】Go語言併發之道 [美] 凱瑟琳(Katherine Cox-Buday)著 PDF 下載Go
- Go語言專案實戰:併發爬蟲Go爬蟲
- GO 語言的併發模式你瞭解多少?Go模式
- 程式設計師修煉之道讀後感02程式設計師
- 程式設計師修煉之道讀後感(1)程式設計師
- 程式設計師修煉之道讀後感(3)程式設計師
- 程式設計師修煉之道讀後感(2)程式設計師
- Go語言 | CSP併發模型與Goroutine的基本使用Go模型
- Go語言併發程式設計簡單入門Go程式設計
- 《快學 Go 語言》第 13 課 —— 併發與安全Go
- Go 語言讀寫 Excel 文件GoExcel
- 《Go 語言程式設計》讀書筆記 (六) 基於共享變數的併發Go程式設計筆記變數
- Go 為什麼不在語言層面支援 map 併發?Go
- 讀後感
- Go高效併發 11 | 併發模式:Go 語言中即學即用的高效併發模式Go模式
- Go語言之併發示例(Runner)Go
- Go語言中的併發模式Go模式
- go語言安卓開發Go安卓
- 程式設計師修煉之道——從小工到專家 的第二章讀後感——注重實效的途徑程式設計師
- 帶讀 |《Go in Action》(中文:Go語言實戰)(一)Go
- nodejs開發指南讀後感NodeJS
- 高效程式設計師的45個習慣-敏捷開發修煉之道(讀後感)程式設計師敏捷
- 【Go 語言入門專欄】Go 語言的起源與發展Go
- 帶讀 |《Go in Action》(中文:Go語言實戰)語法和語言結構概覽 (二)Go
- 帶讀 |《Go in Action》(中文:Go語言實戰) 語法和語言結構概覽(三)Go