Go 天生是為并發(fā)而生的東西。簡(jiǎn)單來(lái)說(shuō),我覺(jué)得并發(fā)可以看作一種程序的構(gòu)造方式,如下圖所示。
并行&并發(fā)
想了解并行和并發(fā)的區(qū)別,推薦看一下Rob Pike的分享(點(diǎn)擊閱讀原文即可跳轉(zhuǎn))。在這個(gè)視頻里,他用形象的Gopher動(dòng)圖,講解了Go并發(fā)的過(guò)程。
總結(jié)他的觀點(diǎn)如下:
因?yàn)榻裉斓闹攸c(diǎn)不是講理論,而是站在可視化的角度來(lái)展示并發(fā)的過(guò)程。所以,結(jié)合這兩個(gè)可視化圖形可以直觀的了解并發(fā)和并行的區(qū)別,畢竟一圖勝千言。(請(qǐng)復(fù)制鏈接在瀏覽器中打開(kāi))
并發(fā):http://talks.bingohuang.com/2017/go-concurrency-visualize/pingpong36.html并行:http://talks.bingohuang.com/2017/go-concurrency-visualize/parallelism.html總的來(lái)說(shuō),并行就是同時(shí)執(zhí)行(通常是相關(guān)的)計(jì)算任務(wù)的編程技術(shù),兩個(gè)或者多個(gè)事件在同一時(shí)刻發(fā)生;而并發(fā)是將相互獨(dú)立的執(zhí)行過(guò)程綜合到一起的編程技術(shù),兩個(gè)或多個(gè)事件在同一時(shí)間間隔內(nèi)發(fā)生。
為什么要關(guān)注并發(fā)?
當(dāng)今是多核的時(shí)代,并發(fā)的世界。摩爾定律逐漸失效,需要更多關(guān)注并發(fā)的編程思想。
但并發(fā)編程并不容易,而?Go 對(duì)并發(fā)有很好的支持。
Go 語(yǔ)言中的并發(fā)
Goroutine?– 并發(fā)執(zhí)行
類似于 UNIX 中的 &很像線程,但更輕量一個(gè) goroutine 就是一個(gè)獨(dú)立運(yùn)行的函數(shù)當(dāng)一個(gè) goroutine 阻塞時(shí),所在的線程會(huì)阻塞,但其它 goroutine 不受影響通過(guò)關(guān)鍵字 go 來(lái)創(chuàng)建 goroutine,如下說(shuō)是
Channel
類似于 UNIX 中的管道它允許在 Goroutine 之間傳遞消息如下有一個(gè)簡(jiǎn)單的例子,這是常見(jiàn)的計(jì)時(shí)器,后續(xù)還可以做成可視化的圖形。
Select
類似于語(yǔ)言中常見(jiàn)的 switch但它的判斷條件是基于通信,而不是基于值的等量匹配Go讓并發(fā)編程變得簡(jiǎn)單起來(lái)
但問(wèn)題來(lái)了:
我們?cè)鯓尤ブv解 Go 的并發(fā)?我們?cè)鯓铀伎?Go 的并發(fā)過(guò)程?最終,我們?cè)鯓痈玫膶?shí)踐 Go 并發(fā)編程?這里祭出一個(gè)法寶——GoTrace,它是一個(gè)能將 Go 并發(fā)過(guò)程可視化的開(kāi)源工具,出自?divan?大神。主要包含兩個(gè)程序:
gotrace(go):分析?go tool trace?的執(zhí)行結(jié)果gothree(js):?基于?ThreeJs?和?WebGL?生成?3D?圖像感謝 divan 大神 提供了這款工具和不少 Go 并發(fā)模式的素材。
耳聽(tīng)為虛,眼見(jiàn)為實(shí)
1.Hello,World!
無(wú)論寫什么語(yǔ)言,都會(huì)從 hello world開(kāi)始,代碼非常簡(jiǎn)單 – 單 channel,單 goroutine,一次寫,一次讀。
效果如下圖(復(fù)制鏈接?http://talks.bingohuang.com/2017/go-concurrency-visualize/helloworld.html?在瀏覽器中打開(kāi)也可直接訪問(wèn)):
這里藍(lán)色的線表示 goroutine 隨著時(shí)間運(yùn)行。細(xì)的藍(lán)線連接了 ‘main’ 和 ‘#20’,標(biāo)志著 goroutine 的啟動(dòng)和停止,揭示了它們的父子關(guān)系。最后,紅色箭頭給我們展示了‘發(fā)送/接受’的動(dòng)作。實(shí)際上它是兩個(gè)獨(dú)立的動(dòng)作,我試著用動(dòng)畫展示成一個(gè)單獨(dú)的事務(wù):從 A 發(fā)送到 B。 Goroutine 名稱中的的 “#20”,是實(shí)際的 goroutine 內(nèi)部 ID,通過(guò)某種手段從運(yùn)行時(shí)獲取。
2.計(jì)時(shí)器
記得在前面講Channel舉的一個(gè)計(jì)時(shí)器的例子,也非常典型 – 創(chuàng)建一個(gè) channel,啟動(dòng)一個(gè) goroutine,在給定的時(shí)間間隔之后向這個(gè) channle 寫入數(shù)據(jù),之后將這個(gè) channel 返回給函數(shù)的調(diào)用著。這個(gè)調(diào)用者會(huì)阻塞固定的時(shí)間后去讀取該 channel。讓我們來(lái)運(yùn)行 24 個(gè)這樣的計(jì)時(shí)器并試著做可視化。
看一下效果(復(fù)制鏈接http://talks.bingohuang.com/2017/go-concurrency-visualize/timer.html):
非常的形象,是不是?
3.兵乓球
兩個(gè)玩家
看一下效果(復(fù)制鏈接?http://talks.bingohuang.com/2017/go-concurrency-visualize/pingpong2.html?到瀏覽器中打開(kāi))
建議在PC端瀏覽器上打開(kāi)上面的鏈接,可以和 WebGL 動(dòng)畫交互,玩玩看。你可以放慢、加快,從不同的角度觀察它。
三個(gè)玩家
上面是常見(jiàn)的2個(gè)乒乓球運(yùn)動(dòng)員對(duì)打的過(guò)程,如果是三個(gè)運(yùn)動(dòng)員會(huì)是什么樣呢?現(xiàn)在,讓我們來(lái)運(yùn)行 3 個(gè)運(yùn)動(dòng)員的試試看。代碼中只要做少量的修改,添加一個(gè) player 即可:
效果如下:(復(fù)制鏈接?http://talks.bingohuang.com/2017/go-concurrency-visualize/pingpong3.html?到瀏覽器中打開(kāi))
36個(gè)玩家
讓我們看一個(gè)更復(fù)雜的例子,跑36個(gè)運(yùn)動(dòng)員看看。
效果(復(fù)制鏈接http://talks.bingohuang.com/2017/go-concurrency-visualize/pingpong36.html?在瀏覽器中打開(kāi))
在這里我們看到每個(gè)運(yùn)動(dòng)員都是輪流依次進(jìn)行,你可能會(huì)想為什么是這樣?為什么接球的 goroutine 會(huì)依照這么嚴(yán)格的順序?
答案是因?yàn)?Go 運(yùn)行時(shí)給接受者(準(zhǔn)備從特定的 channel 接收消息的 goroutines)保持一個(gè)先進(jìn)先出(FIFO)的隊(duì)列,同時(shí)在我們的例子中,每一個(gè)運(yùn)動(dòng)員正好在他將球打到桌子上的時(shí)候就做好準(zhǔn)備。
4.素?cái)?shù)篩
上面幾個(gè)例子比較簡(jiǎn)單,讓我們來(lái)看一個(gè)更復(fù)雜的并發(fā)算法:素?cái)?shù)篩算法,又叫埃拉托斯特尼算法,是一種古老的算法,用于找到小于或等于給定整數(shù)n的素?cái)?shù)。算法核心思想:先用最小的素?cái)?shù)2去篩,把2的倍數(shù)剔除掉;下一個(gè)未篩除的數(shù)就是素?cái)?shù)(這里是3)。再用這個(gè)素?cái)?shù)3去篩,篩除掉3的倍數(shù)… 這樣不斷重復(fù)下去,直到篩完為止。
這個(gè)算法的并發(fā)變化是用 goroutines 來(lái)過(guò)濾數(shù)字 —— 一個(gè) goroutine 發(fā)現(xiàn)一個(gè)素?cái)?shù),而 channels 用來(lái)把數(shù)字從 generator 傳遞到 filter。當(dāng)一個(gè)素?cái)?shù)被找到了,就會(huì)通過(guò) channel 傳遞給 main,再輸出。
當(dāng)然,這個(gè)算法并不會(huì)非常高效,特別是在你想找大量的素?cái)?shù),并且尋找最低的大 O 復(fù)雜度時(shí),但這個(gè)算法確非常的優(yōu)雅。
大家可以看一下可視化的樣子(http://talks.bingohuang.com/2017/go-concurrency-visualize/primesieve.html)
可以在交互模式中體驗(yàn)一下該動(dòng)畫。它的圖形化方式確實(shí)能更好的幫助我們理解算法。該 generate 函數(shù) goroutine 從 2 開(kāi)始發(fā)出每一個(gè)整數(shù)。而每一個(gè)新的 filter 函數(shù) goroutine 會(huì)過(guò)濾特定素?cái)?shù)的倍數(shù) – 2,3,5,7……每一個(gè) filter 的第一個(gè)數(shù)就是素?cái)?shù),將它發(fā)送給 main 函數(shù),并輸出。如果你旋轉(zhuǎn)圖像自頂向下看的話,你會(huì)發(fā)現(xiàn),所有從 goroutine 發(fā)送給 main 的數(shù)字就是素?cái)?shù)。
非常漂亮的算法,特別是在 3D 圖像下。
5.其他-Goroutines? 泄漏??????????
雖然說(shuō)Goroutine是一個(gè)很輕量線程,不應(yīng)該浪費(fèi)它的。假設(shè)有N多個(gè)Goroutine泄漏了會(huì)怎么樣?
效果見(jiàn)http://talks.bingohuang.com/2017/go-concurrency-visualize/leak.html
看起來(lái)很漂亮,但它是一個(gè)定時(shí)炸彈,所以平時(shí)編碼的時(shí)候一定要注意Goroutine泄漏的問(wèn)題。
Gotrace的用法簡(jiǎn)介
最后說(shuō)一下GoTrace的用法,它本身也是開(kāi)源的。
下載方式:go get?-v -u github.com/divan/gotrace
默認(rèn)分支(master)是基于?Go?1.6?開(kāi)發(fā),我建議切換到到 Go18 分支,支持 Go?1.8。
具體用法如下:
直接運(yùn)行?go 代碼的效果并不好,推薦生成 trace,需在執(zhí)行的代碼上前后加上:
結(jié)合?docker ,可以用以下腳本:
它會(huì)自動(dòng)打開(kāi)這個(gè)瀏覽器,可以調(diào)整視角,可以縮放、旋轉(zhuǎn)、加粗,改變圖像。
使用場(chǎng)景
最后我想說(shuō)一下使用場(chǎng)景。首先,我看到的時(shí)候覺(jué)得非??幔@會(huì)引發(fā)大家對(duì)學(xué)習(xí)Go的興趣,同時(shí)還可以通過(guò)它來(lái)學(xué)習(xí) Go 的并發(fā)模式,探索 Go 的并發(fā)過(guò)程,希望對(duì)大家進(jìn)一步學(xué)習(xí) Go 語(yǔ)言有所幫助。
- 閃存普惠,一步到位!華為商業(yè)市場(chǎng)極簡(jiǎn)全閃數(shù)據(jù)中心Pro+重磅發(fā)布
- 《企業(yè)數(shù)據(jù)治理實(shí)踐白皮書》發(fā)布,啟信寶聯(lián)合六大數(shù)交所共同編制
- 業(yè)界首個(gè)!華為數(shù)據(jù)中心自動(dòng)駕駛網(wǎng)絡(luò)通過(guò)EANTC L4自智網(wǎng)絡(luò)等級(jí)測(cè)評(píng)
- AI模型的耗電量驚人 下一步是建設(shè)太空數(shù)據(jù)中心?
- 為什么制造商必須協(xié)調(diào)IT和OT,才能實(shí)現(xiàn)智能工業(yè)的成功?
- 打造AI時(shí)代先進(jìn)算力底座,鯤鵬開(kāi)發(fā)者峰會(huì)2025即將開(kāi)幕
- 金山辦公宣布未來(lái)五年戰(zhàn)略:重建海外基地,優(yōu)化WPS Office用戶體驗(yàn)
- 是德科技攜KAI系列布局AI新時(shí)代
- 微軟全球再裁6000人:無(wú)關(guān)績(jī)效,關(guān)乎未來(lái)
- 華為發(fā)布AI數(shù)據(jù)湖解決方案,助力企業(yè)加速擁抱AI
免責(zé)聲明:本網(wǎng)站內(nèi)容主要來(lái)自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網(wǎng)站出現(xiàn)的信息,均僅供參考。本網(wǎng)站將盡力確保所提供信息的準(zhǔn)確性及可靠性,但不保證有關(guān)資料的準(zhǔn)確性及可靠性,讀者在使用前請(qǐng)進(jìn)一步核實(shí),并對(duì)任何自主決定的行為負(fù)責(zé)。本網(wǎng)站對(duì)有關(guān)資料所引致的錯(cuò)誤、不確或遺漏,概不負(fù)任何法律責(zé)任。任何單位或個(gè)人認(rèn)為本網(wǎng)站中的網(wǎng)頁(yè)或鏈接內(nèi)容可能涉嫌侵犯其知識(shí)產(chǎn)權(quán)或存在不實(shí)內(nèi)容時(shí),應(yīng)及時(shí)向本網(wǎng)站提出書面權(quán)利通知或不實(shí)情況說(shuō)明,并提供身份證明、權(quán)屬證明及詳細(xì)侵權(quán)或不實(shí)情況證明。本網(wǎng)站在收到上述法律文件后,將會(huì)依法盡快聯(lián)系相關(guān)文章源頭核實(shí),溝通刪除相關(guān)內(nèi)容或斷開(kāi)相關(guān)鏈接。