理解并發(fā)、并行的例子
先舉例子來理解這2個概念的區(qū)別。
老師讓兩個同學(xué)去辦公室談話。如果這兩同學(xué)(進(jìn)程)是并列跨過辦公室門(CPU)的,那么就是并行。如果同學(xué)A先進(jìn)同學(xué)B后進(jìn)入(或者先B后A),或者兩人并列同時進(jìn)入,但是在辦公室外的路人甲(用戶)看來,同學(xué)A和同學(xué)B同時都在辦公室內(nèi),這是并發(fā)。
其實這個例子不合理,因為真正的并行是多核CPU下的概念,但上面這個簡單的例子非常有助于理解。
如果舉例要精確一點(diǎn),那么大概是這樣的:進(jìn)辦公室有兩個門(兩CPU),如果兩同學(xué)分別從不同的門進(jìn)入,不管先后性,兩者互相獨(dú)立,那么是并行;如果兩同學(xué)不管以什么方式進(jìn)入,在路人甲看來,他兩同時都在辦公室內(nèi),就是并發(fā)。
我不信到現(xiàn)在還不理解并發(fā)和并行。
并發(fā)和并行的理論性解釋
為什么操作系統(tǒng)上可以同時運(yùn)行多個程序而用戶感覺不出來?
這是因為無論是單CPU還是多CPU,操作系統(tǒng)都營造出了可以同時運(yùn)行多個程序的假象。實際的過程操作系統(tǒng)對進(jìn)程的調(diào)度以及CPU的快速上下文切換實現(xiàn)的:每個進(jìn)程執(zhí)行一會就先停下來,然后CPU切換到下個被操作系統(tǒng)調(diào)度到的進(jìn)程上使之運(yùn)行。因為切換的很快,使得用戶認(rèn)為操作系統(tǒng)一直在服務(wù)自己的程序。
再來解釋并發(fā)就容易理解多了。
并發(fā)(concurrent)指的是多個程序可以同時運(yùn)行的現(xiàn)象,更細(xì)化的是多進(jìn)程可以同時運(yùn)行或者多指令可以同時運(yùn)行。但這不是重點(diǎn),在描述并發(fā)的時候也不會去扣這種字眼是否精確,并發(fā)的重點(diǎn)在于它是一種現(xiàn)象。并發(fā)描述的是多進(jìn)程同時運(yùn)行的現(xiàn)象。但實際上,對于單核心CPU來說,同一時刻只能運(yùn)行一個進(jìn)程。所以,這里的"同時運(yùn)行"表示的不是真的同一時刻有多個進(jìn)程運(yùn)行的現(xiàn)象,這是并行的概念,而是提供一種功能讓用戶看來多個程序同時運(yùn)行起來了,但實際上這些程序中的進(jìn)程不是一直霸占CPU的,而是執(zhí)行一會停一會。
所以,并發(fā)和并行的區(qū)別就很明顯了。它們雖然都說是"多個進(jìn)程同時運(yùn)行",但是它們的"同時"不是一個概念。并行的"同時"是同一時刻可以多個進(jìn)程在運(yùn)行(處于running),并發(fā)的"同時"是經(jīng)過上下文快速切換,使得看上去多個進(jìn)程同時都在運(yùn)行的現(xiàn)象,是一種OS欺騙用戶的現(xiàn)象。
實際上,當(dāng)程序中寫下多進(jìn)程或多線程代碼時,這意味著的是并發(fā)而不是并行。并發(fā)是因為多進(jìn)程/多線程都是需要去完成的任務(wù),不并行是因為并行與否由操作系統(tǒng)的調(diào)度器決定,可能會讓多個進(jìn)程/線程被調(diào)度到同一個CPU核心上。只不過調(diào)度算法會盡量讓不同進(jìn)程/線程使用不同的CPU核心,所以在實際使用中幾乎總是會并行,但卻不能以100%的角度去保證會并行。也就是說,并行與否程序員無法控制,只能讓操作系統(tǒng)決定。
再次注明,并發(fā)是一種現(xiàn)象,之所以能有這種現(xiàn)象的存在,和CPU的多少無關(guān),而是和進(jìn)程調(diào)度以及上下文切換有關(guān)的。
理解了概念,再來深入擴(kuò)展下。
串行、并行和并發(fā)
任務(wù)描述
如圖:
任務(wù)是將左邊的一堆柴全部搬到右邊燒掉,每個任務(wù)包括三個過程:取柴,運(yùn)柴,放柴燒火。
這三個過程分別對應(yīng)一個函數(shù):
串行模式
串行表示所有任務(wù)都一一按先后順序進(jìn)行。串行意味著必須先裝完一車柴才能運(yùn)送這車柴,只有運(yùn)送到了,才能卸下這車柴,并且只有完成了這整個三個步驟,才能進(jìn)行下一個步驟。
和稍后所解釋的并行相對比,串行是一次只能取得一個任務(wù),并執(zhí)行這個任務(wù)。
假設(shè)這堆柴需要運(yùn)送4次才能運(yùn)完,那么當(dāng)寫下的代碼類似于下面這種時,那么就是串行非并發(fā)的模式:
get()
carry()
unload()
}
或者,將三個過程的代碼全部集中到一個函數(shù)中也是如此:
geting
carrying
unloading
}
for(i=0;i<4;i++){
task()
}
這兩種都是串行的代碼模式。畫圖描述:
并行模式
并行意味著可以同時取得多個任務(wù),并同時去執(zhí)行所取得的這些任務(wù)。并行模式相當(dāng)于將長長的一條隊列,劃分成了多條短隊列,所以并行縮短了任務(wù)隊列的長度。
正如前面所舉的兩同學(xué)進(jìn)辦公室的例子,串行的方式下,必須1個同學(xué)進(jìn)入后第二個同學(xué)才進(jìn)入,隊列長度為2,而并行方式下可以同時進(jìn)入,隊列長度減半了。
并行的效率從代碼層次上強(qiáng)依賴于多進(jìn)程/多線程代碼,從硬件角度上則依賴于多核CPU。
對于單進(jìn)程/單線程,由于只有一個進(jìn)程/線程在執(zhí)行,所以盡管同時執(zhí)行所取得的多個任務(wù),但實際上這個進(jìn)程/線程是不斷的在多任務(wù)之間切換,一會執(zhí)行一下這個,一會執(zhí)行一下那個,就像是一個人在不同地方之間來回奔波。所以,單進(jìn)程/線程的并行,效率比串行更低。
對于多進(jìn)程/多線程,各進(jìn)程/線程都可以執(zhí)行各自所取得的任務(wù),這是真正的并行。
但是,還需要考慮硬件層次上CPU核心數(shù),如果只有單核CPU,那么在硬件角度上這單核CPU一次也只能執(zhí)行一個任務(wù),上面多進(jìn)程/多線程的并行也并非真正意義上的并行。只有多核CPU,并且多進(jìn)程/多線程并行,才是真正意義上的并行。
如下圖,是多進(jìn)程/多線程(2個工作者)的并行:
并發(fā)
并發(fā)表示多個任務(wù)同時都要執(zhí)行的現(xiàn)象,更詳細(xì)的概念前面已經(jīng)說面的夠具體了。
其實,很多場景下都會使用并發(fā)的概念。比如同時500個http請求涌向了web服務(wù)器,比如有時候說并發(fā)數(shù)是1000等。
有時候也將并發(fā)當(dāng)成任務(wù),比如500并發(fā)數(shù)意味著500個任務(wù),表示的是在一個特定的時間段內(nèi)(約定俗成的大家認(rèn)為是1秒)可以完成500個任務(wù)。這500個任務(wù)可以是單進(jìn)程/單線程方式處理的,這時表示的是并發(fā)不并行的模式(coroutine就是典型的并發(fā)不并行),即先執(zhí)行完一個任務(wù)后才執(zhí)行另一個任務(wù),也可以是多進(jìn)程/多線程方式處理的,這時表示的是并發(fā)且并行模式。
要解決大并發(fā)問題,通常是將大任務(wù)分解成多個小任務(wù)。很典型的一個例子是處理客戶端的請求任務(wù),這個大任務(wù)里面包含了監(jiān)聽并建立客戶端的連接、處理客戶端的請求、響應(yīng)客戶端。但基本上所有這類程序,都將這3部分任務(wù)分開了:在執(zhí)行任何一個小任務(wù)的時候,都可以通過一些手段使得可以執(zhí)行其它小任務(wù),比如在處理請求的時候,可以繼續(xù)保持監(jiān)聽狀態(tài)。
由于操作系統(tǒng)對進(jìn)程的調(diào)度是隨機(jī)的,所以切分成多個小任務(wù)后,可能會從任一小任務(wù)處執(zhí)行。這可能會出現(xiàn)一些現(xiàn)象:
- 可能出現(xiàn)一個小任務(wù)執(zhí)行了多次,還沒開始下個任務(wù)的情況。這時一般會采用隊列或類似的數(shù)據(jù)結(jié)構(gòu)來存放各個小任務(wù)的成果。比如負(fù)責(zé)監(jiān)聽的進(jìn)程已經(jīng)執(zhí)行了多次,建立了多個連接,但是還沒有調(diào)度到處理請求的進(jìn)程去處理任何一個請求。
- 可能出現(xiàn)還沒準(zhǔn)備好第一步就執(zhí)行第二步的可能。這時,一般采用多路復(fù)用或異步的方式,比如只有準(zhǔn)備好產(chǎn)生了事件通知才執(zhí)行某個任務(wù)。比如還沒有和任何一個客戶端建立連接時,就去執(zhí)行了處理請求的進(jìn)程。
- 可以多進(jìn)程/多線程的方式并行執(zhí)行這些小任務(wù)。也可以單進(jìn)程/單線程執(zhí)行這些小任務(wù),這時很可能要配合多路復(fù)用才能達(dá)到較高的效率
看圖非常容易理解:
上圖中將一個任務(wù)中的三個步驟取柴、運(yùn)柴、卸柴劃分成了獨(dú)立的小任務(wù),有取柴的老鼠,有運(yùn)柴的老鼠,有卸柴燒火的老鼠。
如果上圖中所有的老鼠都是同一只,那么是串行并發(fā)的,如果是不同的多只老鼠,那么是并行并發(fā)的。
總結(jié)
并行和串行:
- 串行:一次只能取得一個任務(wù)并執(zhí)行這一個任務(wù)
- 并行:可以同時通過多進(jìn)程/多線程的方式取得多個任務(wù),并以多進(jìn)程或多線程的方式同時執(zhí)行這些任務(wù)
- 注意點(diǎn):
- 如果是單進(jìn)程/單線程的并行,那么效率比串行更差
- 如果只有單核cpu,多進(jìn)程并行并沒有提高效率
- 從任務(wù)隊列上看,由于同時從隊列中取得多個任務(wù)并執(zhí)行,相當(dāng)于將一個長任務(wù)隊列變成了短隊列
并發(fā):
- 并發(fā)是一種現(xiàn)象:同時運(yùn)行多個程序或多個任務(wù)需要被處理的現(xiàn)象
- 這些任務(wù)可能是并行執(zhí)行的,也可能是串行執(zhí)行的,和CPU核心數(shù)無關(guān),是操作系統(tǒng)進(jìn)程調(diào)度和CPU上下文切換達(dá)到的結(jié)果
- 解決大并發(fā)的一個思路是將大任務(wù)分解成多個小任務(wù):
- 可能要使用一些數(shù)據(jù)結(jié)構(gòu)來避免切分成多個小任務(wù)帶來的問題
- 可以多進(jìn)程/多線程并行的方式去執(zhí)行這些小任務(wù)達(dá)到高效率
- 或者以單進(jìn)程/單線程配合多路復(fù)用執(zhí)行這些小任務(wù)來達(dá)到高效率
-
cpu
+關(guān)注
關(guān)注
68文章
11049瀏覽量
216129 -
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
7103瀏覽量
125041 -
并行
+關(guān)注
關(guān)注
0文章
80瀏覽量
19230 -
程序
+關(guān)注
關(guān)注
117文章
3824瀏覽量
82498
發(fā)布評論請先 登錄
實時操作系統(tǒng)和分時操作系統(tǒng)的區(qū)別
Linux與其他操作系統(tǒng)的區(qū)別
POS機(jī)的linux操作系統(tǒng)和android系統(tǒng)區(qū)別!
Java操作系統(tǒng)支持多線程
操作系統(tǒng)的特點(diǎn)?
uCOS-II實時操作系統(tǒng)實時操作系統(tǒng)與分時操作系統(tǒng)的區(qū)別是什么
實時操作系統(tǒng)和Linux分時操作系統(tǒng)有哪些區(qū)別呢
裸機(jī)與帶嵌入式開發(fā)的操作系統(tǒng)有何區(qū)別
操作系統(tǒng)講解(操作系統(tǒng)課件)
Linux與其他操作系統(tǒng)的區(qū)別
并行和并發(fā)哪個好?并行和并發(fā)的概念和區(qū)別

Linux操作系統(tǒng)與Windows操作系統(tǒng)的五大區(qū)別
實時操作系統(tǒng)和非實時操作系統(tǒng)的區(qū)別
裸機(jī)開發(fā)和帶操作系統(tǒng)開發(fā)的區(qū)別

嵌入式實時操作系統(tǒng):Intewell操作系統(tǒng)與VxWorks操作系統(tǒng)有啥區(qū)別

評論