OK,如果你還在為并發(fā)(concurrency)和并行(parallelism)這兩個詞的區(qū)別而感到困擾锌半,那么這篇文章就是寫給你看的。搞這種詞語辨析到底有什么意義?其實沒什么意義土思,但是有太多人在混用錯用這兩個詞(比如遇到的某門課的老師)。不論中文圈還是英文圈忆嗜,即使已經(jīng)有數(shù)不清的文章在討論并行vs并發(fā)己儒,卻極少有能講清楚的。讓一個講不清楚的人來解釋捆毫,比不解釋更可怕闪湾。比如我隨便找了個網(wǎng)上的解釋
前者是邏輯上的同時發(fā)生(simultaneous),而后者是物理上的同時發(fā)生.
并發(fā)性(concurrency)绩卤,又稱共行性途样,是指能處理多個同時性活動的能力,并發(fā)事件之間不一定要同一時刻發(fā)生濒憋。
并行(parallelism)是指同時發(fā)生的兩個并發(fā)事件何暇,具有并發(fā)的含義,而并發(fā)則不一定并行凛驮。
來個比喻:并發(fā)和并行的區(qū)別就是一個人同時吃三個饅頭和三個人同時吃三個饅頭裆站。
看了之后,你懂了么辐烂?不懂遏插,更暈了。寫出這類解釋的人纠修,自己也是一知半解胳嘲,卻又把自己腦子里模糊的影像拿出來寫成文章,讓讀者閱畢反而更加疑惑扣草。當然也有可能他確實懂了了牛,但是寫出這種文字也不能算負責颜屠。至于本文,請相信鹰祸,一定是準確的甫窟,我也盡量做到講解清晰。
OK蛙婴,下面進入正題粗井,concurrency vs parallelism
讓我們大聲朗讀下面這句話:
“并發(fā)”指的是程序的結(jié)構(gòu),“并行”指的是程序運行時的狀態(tài)
即使不看詳細解釋街图,也請記住這句話浇衬。下面來具體說說:
并行(parallelism)
這個概念很好理解。所謂并行餐济,就是同時執(zhí)行的意思耘擂,無需過度解讀。判斷程序是否處于并行的狀態(tài)絮姆,就看同一時刻是否有超過一個“工作單位”在運行就好了醉冤。所以,單線程永遠無法達到并行狀態(tài)篙悯。
要達到并行狀態(tài)蚁阳,最簡單的就是利用多線程和多進程。但是 Python 的多線程由于存在著名的 GIL辕近,無法讓兩個線程真正“同時運行”韵吨,所以實際上是無法到達并行狀態(tài)的。
并發(fā)(concurrency)
要理解“并發(fā)”這個概念移宅,必須得清楚,并發(fā)指的是程序的“結(jié)構(gòu)”椿疗。當我們說這個程序是并發(fā)的漏峰,實際上,這句話應(yīng)當表述成“這個程序采用了支持并發(fā)的設(shè)計”届榄。好浅乔,既然并發(fā)指的是人為設(shè)計的結(jié)構(gòu),那么怎樣的程序結(jié)構(gòu)才叫做支持并發(fā)的設(shè)計铝条?
正確的并發(fā)設(shè)計的標準是:使多個操作可以在重疊的時間段內(nèi)進行(two tasks can start, run, and complete in overlapping time periods)靖苇。
這句話的重點有兩個。我們先看“(操作)在重疊的時間段內(nèi)進行”這個概念班缰。它是否就是我們前面說到的并行呢贤壁?是,也不是埠忘。并行脾拆,當然是在重疊的時間段內(nèi)執(zhí)行馒索,但是另外一種執(zhí)行模式,也屬于在重疊時間段內(nèi)進行名船。這就是協(xié)程绰上。
使用協(xié)程時,程序的執(zhí)行看起來往往是這個樣子:
task1, task2 是兩段不同的代碼渠驼,比如兩個函數(shù)蜈块,其中黑色塊代表某段代碼正在執(zhí)行。注意迷扇,這里從始至終疯趟,在任何一個時間點上都只有一段代碼在執(zhí)行,但是谋梭,由于 task1 和 task2 在重疊的時間段內(nèi)執(zhí)行信峻,所以這是一個支持并發(fā)的設(shè)計。與并行不同瓮床,單核單線程能支持并發(fā)盹舞。
經(jīng)常看到這樣一個說法隘庄,叫做并發(fā)執(zhí)行√卟剑現(xiàn)在我們可以正確理解它。有兩種可能:
- 原本想說的是“并行執(zhí)行”丑掺,但是用錯了詞
- 指多個操作可以在重疊的時間段內(nèi)進行获印,即,真的并行街州,或是類似上圖那樣的執(zhí)行模式兼丰。
我的建議是盡可能不使用這個詞,容易造成誤會唆缴,尤其是對那些并發(fā)并行不分的人鳍征。但是讀到這里的各位顯然能正確區(qū)分,所以下面為了簡便面徽,將使用并發(fā)執(zhí)行這個詞艳丛。
第二個重點是“可以在重疊的時間段內(nèi)進行”中的“可以”兩個字√宋桑“可以”的意思是氮双,正確的并發(fā)設(shè)計使并發(fā)執(zhí)行成為可能,但是程序在實際運行時卻不一定會出現(xiàn)多個任務(wù)執(zhí)行時間段 overlap 的情形霎匈。比如:我們的程序會為每個任務(wù)開一個線程或者協(xié)程戴差,只有一個任務(wù)時,顯然不會出現(xiàn)多個任務(wù)執(zhí)行時間段重疊的情況唧躲,有多個任務(wù)時造挽,就會出現(xiàn)了碱璃。這里我們看到,并發(fā)并不描述程序執(zhí)行的狀態(tài)饭入,它描述的是一種設(shè)計嵌器,是程序的結(jié)構(gòu),比如上面例子里“為每個任務(wù)開一個線程”的設(shè)計谐丢。并發(fā)設(shè)計和程序?qū)嶋H執(zhí)行情況沒有直接關(guān)聯(lián)爽航,但是正確的并發(fā)設(shè)計讓并發(fā)執(zhí)行成為可能。反之乾忱,如果程序被設(shè)計為執(zhí)行完一個任務(wù)再接著執(zhí)行下一個讥珍,那就不是并發(fā)設(shè)計了,因為做不到并發(fā)執(zhí)行窄瘟。
那么衷佃,如何實現(xiàn)支持并發(fā)的設(shè)計?兩個字:拆分蹄葱。
之所以并發(fā)設(shè)計往往需要把流程拆開氏义,是因為如果不拆分也就不可能在同一時間段進行多個任務(wù)了。這種拆分可以是平行的拆分图云,比如抽象成同類的任務(wù)惯悠,也可以是不平行的,比如分為多個步驟竣况。
并發(fā)和并行的關(guān)系
Different concurrent designs enable different ways to parallelize.
這句話來自著名的talk: Concurrency is not parallelism克婶。它足夠concise,以至于不需要過多解釋丹泉。但是僅僅引用別人的話總是不太好情萤,所以我再用之前文字的總結(jié)來說明:并發(fā)設(shè)計讓并發(fā)執(zhí)行成為可能,而并行是并發(fā)執(zhí)行的一種模式嘀掸。
最后紫岩,關(guān)于Concurrency is not parallelism這個talk再多說點。自從這個talk出來睬塌,直接引爆了一堆討論并發(fā)vs并行的文章,并且無一例外提到這個talk歇万,甚至有的文章直接用它的slide里的圖片來說明揩晴。比如這張:
以為我要解釋這張圖嗎?NO贪磺。放這張圖的唯一原因就是萌萌的gopher硫兰。
再來張?zhí)貙懀?/p>
之前看到知乎上有個關(guān)于go為什么流行的問題,有個答案是“l(fā)ogo萌”當時我就笑噴了寒锚。
好像跑題了劫映,繼續(xù)說這個 talk违孝。和很多人一樣,我也是看了這個 talk 才開始思考 concurrency vs parallesim 的問題泳赋。為了研究那一堆推小車的 gopher 到底是怎么回事雌桑,我花費了相當多的時間。實際上后來我更多地是通過網(wǎng)上的只言片語(比如SO的回答)和自己的思考弄清了這個問題祖今,talk 并沒有很大幫助校坑。徹底明白之后再回過頭來看這個 talk,確實相當不錯千诬,Andrew Gerrand 對這個問題的理解絕對夠深刻耍目,但是太不新手向了。最大問題在于徐绑,那一堆 gopher 的例子不夠好邪驮,太復雜。Andrew Gerrand 花了大把時間來講述不同的并發(fā)設(shè)計傲茄,但是作為第一次接觸這個話題的人毅访,在沒有搞清楚并發(fā)并行區(qū)別的情況下就去研究推小車的 gopher,太難了烫幕“吵椋“Different concurrent designs enable different ways to parallelize” 這句總結(jié)很精辟,但也只有那些已經(jīng)透徹理解的人才能領(lǐng)會较曼,比如我和看到這里的讀者磷斧,對新手來說就和經(jīng)文一樣難懂〗萦蹋總結(jié)下來一句話弛饭,不要一開始就去看這個視頻,也不要花時間研究推小車的gopher萍歉。Gopher is moe, but confusing.
最關(guān)鍵的一點是侣颂,計算機在不同層次上都使用了并行技術(shù)。之前我討論的實際上僅限于 Task-Level 這一層枪孩,在這一層上憔晒,并行無疑是并發(fā)的一個子集。但是并行并非并發(fā)的子集蔑舞,因為在 Bit-Level 和 Instruction-Level 上的并行不屬于并發(fā)——比如引文中舉的 32 位計算機執(zhí)行 32 位數(shù)加法的例子拒担,同時處理 4 個字節(jié)顯然是一種并行,但是它們都屬于 32 位加法這一個任務(wù)攻询,并不存在多個任務(wù)从撼,也就根本沒有并發(fā)。
所以钧栖,正確的說法是這樣:
并行指物理上同時執(zhí)行低零,并發(fā)指能夠讓多個任務(wù)在邏輯上交織執(zhí)行的程序設(shè)計
按照我現(xiàn)在的理解婆翔,并發(fā)針對的是 Task-Level 及更高層,并行則不限掏婶。這也是它們的區(qū)別啃奴。
原文:https://laike9m.com/blog/huan-zai-yi-huo-bing-fa-he-bing-xing,61/