Java併發程式設計三:併發(Concurrent)與並行(Parallel)的區別(一)
併發(Concurrent)與並行(Parallel)是一個大家比較容易混淆的概念。大家在解釋併發與並行的時候一般這樣說:
- 多執行緒是併發執行的;
- 多核CPU是並行執行的,單核CPU是不可以不行執行的;
以上說法也是可以理解的,大家都是基於場景來描述的。為了搞清楚這個問題,我查閱了一些資料,發現這篇譯文:併發不是並行,它更好中的圖片很好的說明了併發與並行的區別。
定義
網路上找到的定義如下:
併發(Concurrent):以可獨立執行的程序集合的方式程式設計(程序是出了名的難定義,這裡是通常意義上的程序,不是Linux程序)。
並行(Parallel):以可同時執行的(可能相關的)計算指令方式程式設計。
我的理解:
併發(Concurrent):是一種構造程式的方式,把任務分解為一個個獨立執行的小任務。通訊是協調這些小任務的手段。
並行(Parallel):以分組的方式,同時執行每一組併發任務。
兩者的區別:併發是同時處理(dealing)很多的事情,並行是同時做(doing)很多的事情。
以上的講解太抽象了,我們通過例項來講解,舉例如下:
我們的問題:把一堆廢棄的說明書運到火爐裡,一隻地鼠會花費很長時間。
方案一
一隻地鼠,使用一輛推車,將書裝到車上,運輸到火爐旁,將書卸到火爐。
方案二
有兩隻地鼠,一隻地鼠,使用一輛推車,將書裝到車上,運輸到火爐旁,將書卸到火爐。另一隻地鼠出於等待中,顯然增加更多的地鼠是無法解決效率問題的,也需要同時增加推車。(當然有人說兩隻地鼠輪流使用一輛推車,這樣可以讓地鼠得到休息,這樣它們幹活更快,也可以提高效率。)
方案三
兩隻地鼠,兩輛推車,分別使用各自的推車,將書裝到車上,運輸到火爐旁,將書卸到火爐。這樣會提高運輸效率,但它們會在裝書和卸書時進行排隊,降低了效率。
方案四
基於方案一的改進,將書堆拆分成兩部分,同時增加一個火爐。該方案有兩種可能:
1、只地鼠運一次上面那堆書,然後第二隻地鼠再運一次下面那堆書。一次只允許一隻地鼠運送,這樣就不是並行的。
2、兩隻地鼠,兩輛推車,分別使用各自的推車,把各自書堆的書裝到車上,運輸到各自的火爐旁,將書卸到火爐。這樣提高了運輸效率,而且在裝書和卸書時不會進行排隊,提高了裝卸的效率。
方案五
三隻地鼠在工作,一隻負責把書裝到車上,一隻負責運輸,一隻負責把書卸到火爐。每隻地鼠做一個獨立的任務。
方案六
四隻地鼠在工作,一隻負責把書裝到車上,一隻負責運輸,一隻負責把書卸到火爐,一隻負責運回空推車。每隻地鼠做一個獨立的任務。
觀察結論:我們在一個已有的設計(指三個地鼠的那個設計)中新增一個併發的步驟(第四隻地鼠)增強了系統的效能。更多的地鼠幹了更多的活,系統執行得更好。併發比簡單的並行對問題要有更深的洞察。
我們有四個併發的步驟:
1. 把書裝到車上;
2. 把推車運到火爐旁;
3. 把書卸到火爐裡;
4. 運回空推車。
不同的併發設計能以不同的方式來並行。
方案七
增加一個方案六的分組,使兩個分組並行執行。
方案八
兩隻地鼠,再加上一個中轉堆。這也是一種用併發來解決問題的方案。
方案九
增加一個方案八的分組,使兩個分組並行執行。
方案十
在多地鼠併發模型中引入中轉堆
方案十一
增加一個方案十的分組,使兩個分組並行執行。
總結
我們有很多方法把問題分解,這才是併發設計。一旦我們分解了問題,並行就自然而然的產生了。
回到兩者的區別這個問題上:
併發是同時處理(dealing)很多的事情,如方案六,同時處理一下四個併發步驟:
1. 把書裝到車上;
2. 把推車運到火爐旁;
3. 把書卸到火爐裡;
4. 運回空推車。
並行是同時做(doing)很多的事情,如方案十一,分為兩組同時執行任務。這就是我對併發與並行的理解。