併發不是並行 它更好!
現代社會是並行的:多核、網路、雲端計算、使用者負載,併發技術對此有用。
Go語言支援併發,它提供了:併發執行(goroutines),同步和訊息(channels)和多路併發控制(select)。
當Go聲稱是併發時,人們說:“併發很酷!耶,我可以並行執行了!”,但這是個錯誤的。因為很多人都不瞭解他們間的差別。“我用四個處理器來做質數篩選,但是更慢了。”
併發(Concurrency):以可獨立執行的程式集合的方式程式設計(程式是出了名的難定義,這裡是通常意義上的程式,不是Linux程式)
並行(Parallelism):以可同時執行的(可能相關的)計算指令方式程式設計。
兩者的區別:併發是同時處理(dealing)很多的事情,並行是同時做(doing)很多的事情。不同,但也相關。一個是關於程式碼結構,一個是關於程式碼執行。併發為可能的(不是必須的)並行問題提供了一種解決方案。
一個類比:
滑鼠、鍵盤、顯示器、磁碟驅動是併發結構的。
向量點積是並行的。
併發帶有通訊:
併發是一種構造程式的方式,把任務分解為一個個獨立執行的小任務。通訊是協調這些小任務的手段。
Go的模型(還有Erlang等)都是基於CPS(Communicating sequential processes, 通訊順序程式):其論文C. A. R. Hoare: Communicating Sequential Processes (CACM 1978)
以上講得太抽象了,我們舉實際點的例子。
我們的問題:把一堆廢棄語言的說明書運到火爐裡,一隻地鼠會花費很長時間。
更多的地鼠
單單更多的地鼠也不解決問題,它們需要更多的推車。
更多的地鼠、更多的推車
這樣會加快速度,但它們會在那堆書和爐子那邊遇上瓶頸。同時也要同步兩隻地鼠,可以通過訊息的方式實現。
全部加倍
這樣會以兩倍的速度運送。這是兩個地鼠程式的併發構成(concurrent composition)。
但這種設計不是自發並行的,如果一次只有一隻地鼠在運會怎樣?
這種設計仍是併發,不是並行。[譯者注:一隻地鼠運一次上面那堆書,然後第二隻地鼠再運一次下面那堆書。一次只允許一隻地鼠運送,這樣就不是並行的。
然而,這種場景是可以自發並行的。併發構成可以考慮下其他模型。
另一種設計
三隻地鼠在工作,但可能會有延誤。每隻地鼠是個獨立的步驟,附加協調(通訊)。
更細粒度的併發
增加一隻地鼠用來運回空推車。四隻地鼠在工作,執行得更加流暢,每隻地鼠都在做一個簡單的任務。
如果我們把事情安排的足夠好(現實中很難但不是不可能),速度會是最先只有一隻地鼠的那個設計的四倍。
觀察結論:我們在一個已有的設計(指三個地鼠的那個設計)中新增一個併發的步驟(第四隻地鼠)增強了系統的效能。更多的地鼠幹了更多的活,系統執行得更好。併發比簡單的並行對問題要有更深的洞察。
我們有四個併發的步驟:1.裝書到推車上2.把推車運到火爐邊3.把書卸到火爐裡4.運回空推車
不同的併發設計能以不同的方式來並行。
更多的並行
我們以另一個維度來並行,並行使這樣的設計變的容易。八隻地鼠,都在繁忙工作。
但也可能根本沒有並行
謹記:即使一次只能有一隻地鼠在工作(零並行),這也不失為一個良好的併發的解決方案。
另一種設計
下面也是一種用併發組成來解決問題的設計。兩隻地鼠,再加上一個中轉堆。
以一般的方式來並行
用更多的併發程式來提高吞吐量
或者一種不同的方式
在多地鼠併發模型中引入中轉堆
全面優化
使用我們所有的技術,16只地鼠都開足馬力。
學到內容
我們有很多方法把問題分解,這才是併發設計。一旦我們分解了問題,並行就自然而然的產生了,正確性也變得很容易。
回到計算
我們關於運書的問題,可以看做是如下的類比:書堆是Web資料,地鼠是CPU,推車是排程、渲染或是網路,火堆是代理、瀏覽器或是其他的消費者。地鼠提供網路資料,這就是一個可擴充套件的Web服務的併發設計了。
相關文章
- Java併發(一)----程式、執行緒、並行、併發Java執行緒並行
- 快速理解併發、並行並行
- Python的 併發、並行Python並行
- 深入理解併發和並行並行
- 【連載 01】併發與並行並行
- 架構之:併發和並行架構並行
- [Java併發]執行緒的並行等待Java執行緒並行
- 執行緒 並行 與 併發 的區別執行緒並行
- .NET併發程式設計-資料並行程式設計並行
- 併發程式設計-8.並行資料結構和並行Linq程式設計並行資料結構
- 並行化-你的高併發大殺器並行
- 吃個快餐都能學到序列、並行、併發並行
- 【作業系統】3.併發和並行作業系統並行
- 手寫演算法並記住它:歸併排序演算法排序
- 程式執行緒、同步非同步、阻塞非阻塞、併發並行執行緒非同步並行
- .NET併發程式設計-任務函式並行程式設計函式並行
- 執行緒,程式,協程, 併發,並行,同步,非同步概念解析執行緒並行非同步
- 全網最適合入門的物件導向程式設計教程:59 Python並行與併發-並行與併發和執行緒與程序物件程式設計Python並行執行緒
- 我已經理解了併發和並行的區別並行
- ♻️同步和非同步;並行和併發;阻塞和非阻塞非同步並行
- .NET併發程式設計-TPL Dataflow並行工作流程式設計並行
- Nginx 高階篇(十)並行 併發 單執行緒(廢話篇 )Nginx並行執行緒
- 改造vue-cli,讓它更好用Vue
- 如何給女朋友解釋什麼是併發和並行並行
- Golang非CSP併發模型外的其他並行方法總結Golang模型並行
- goroutine併發執行多個任務並依次返回結果Go
- 透過一個示例形象地理解C# async await 非並行非同步、並行非同步、並行非同步的併發量控制C#AI並行非同步
- 【OS】同步非同步/阻塞非阻塞、併發並行序列的區分非同步並行
- 分散式鎖不是控制併發冪等的方式分散式
- 程式與執行緒、同步與非同步、阻塞與非阻塞、併發與並行執行緒非同步並行
- 圖解併發與並行-分別從CPU和執行緒的角度理解圖解並行執行緒
- 漫話:如何給女朋友解釋什麼是併發和並行並行
- 同步容器(如Vector)並不是所有操作都執行緒安全!~執行緒
- 併發程式設計-7.任務並行庫(TPL)和資料流程式設計並行
- java多執行緒與併發 - 併發工具類Java執行緒
- 66.QT-執行緒併發、QTcpServer併發、QThreadPool執行緒池QT執行緒TCPServerthread
- 一文講明白Java中執行緒與程序、併發與並行、同步與非同步Java執行緒並行非同步
- goroutine併發執行多個任務並依次返回結果2——sync.WaitGroupGoAI
- 並行開發基礎並行