進(jìn)程,線程,協(xié)程與并行,并發(fā)

進(jìn)程

進(jìn)程的出現(xiàn)是為了更好的利用CPU資源使到并發(fā)成為可能。 假設(shè)有兩個(gè)任務(wù)A和B,當(dāng)A遇到IO操作,CPU默默的等待任務(wù)A讀取完操作再去執(zhí)行任務(wù)B,這樣無(wú)疑是對(duì)CPU資源的極大的浪費(fèi)。聰明的老大們就在想若在任務(wù)A讀取數(shù)據(jù)時(shí),讓任務(wù)B執(zhí)行,當(dāng)任務(wù)A讀取完數(shù)據(jù)后,再切換到任務(wù)A執(zhí)行。注意關(guān)鍵字切換,自然是切換,那么這就涉及到了狀態(tài)的保存,狀態(tài)的恢復(fù),加上任務(wù)A與任務(wù)B所需要的系統(tǒng)資源(內(nèi)存,硬盤,鍵盤等等)是不一樣的。自然而然的就需要有一個(gè)東西去記錄任務(wù)A和任務(wù)B分別需要什么資源,怎樣去識(shí)別任務(wù)A和任務(wù)B等等。登登登,進(jìn)程就被發(fā)明出來(lái)了。通過(guò)進(jìn)程來(lái)分配系統(tǒng)資源,標(biāo)識(shí)任務(wù)。如何分配CPU去執(zhí)行進(jìn)程稱之為調(diào)度,進(jìn)程狀態(tài)的記錄,恢復(fù),切換稱之為上下文切換。進(jìn)程是系統(tǒng)資源分配的最小單位,進(jìn)程占用的資源有:地址空間,全局變量,文件描述符,各種硬件等等資源。

線程

線程的出現(xiàn)是為了降低上下文切換的消耗,提高系統(tǒng)的并發(fā)性,并突破一個(gè)進(jìn)程只能干一樣事的缺陷,使到進(jìn)程內(nèi)并發(fā)成為可能。假設(shè),一個(gè)文本程序,需要接受鍵盤輸入,將內(nèi)容顯示在屏幕上,還需要保存信息到硬盤中。若只有一個(gè)進(jìn)程,勢(shì)必造成同一時(shí)間只能干一樣事的尷尬(當(dāng)保存時(shí),就不能通過(guò)鍵盤輸入內(nèi)容)。若有多個(gè)進(jìn)程,每個(gè)進(jìn)程負(fù)責(zé)一個(gè)任務(wù),進(jìn)程A負(fù)責(zé)接收鍵盤輸入的任務(wù),進(jìn)程B負(fù)責(zé)將內(nèi)容顯示在屏幕上的任務(wù),進(jìn)程C負(fù)責(zé)保存內(nèi)容到硬盤中的任務(wù)。這里進(jìn)程A,B,C間的協(xié)作涉及到了進(jìn)程通信問(wèn)題,而且有共同都需要擁有的東西-------文本內(nèi)容,不停的切換造成性能上的損失。若有一種機(jī)制,可以使任務(wù)A,B,C共享資源,這樣上下文切換所需要保存和恢復(fù)的內(nèi)容就少了,同時(shí)又可以減少通信所帶來(lái)的性能損耗,那就好了。是的,這種機(jī)制就是線程。線程共享進(jìn)程的大部分資源,并參與CPU的調(diào)度, 當(dāng)然線程自己也是擁有自己的資源的,例如,棧,寄存器等等。 此時(shí),進(jìn)程同時(shí)也是線程的容器。線程也是有著自己的缺陷的,例如健壯性差,若一個(gè)線程掛掉了,整一個(gè)進(jìn)程也掛掉了,這意味著其它線程也掛掉了,進(jìn)程卻沒(méi)有這個(gè)問(wèn)題,一個(gè)進(jìn)程掛掉,另外的進(jìn)程還是活著。

協(xié)程

協(xié)程通過(guò)在線程中實(shí)現(xiàn)調(diào)度,避免了陷入內(nèi)核級(jí)別的上下文切換造成的性能損失,進(jìn)而突破了線程在IO上的性能瓶頸。 當(dāng)涉及到大規(guī)模的并發(fā)連接時(shí),例如10K連接。以線程作為處理單元,系統(tǒng)調(diào)度的開(kāi)銷還是過(guò)大。當(dāng)連接數(shù)很多 —> 需要大量的線程來(lái)干活 —> 可能大部分的線程處于ready狀態(tài) —> 系統(tǒng)會(huì)不斷地進(jìn)行上下文切換。既然性能瓶頸在上下文切換,那解決思路也就有了,在線程中自己實(shí)現(xiàn)調(diào)度,不陷入內(nèi)核級(jí)別的上下文切換。說(shuō)明一下,在歷史上協(xié)程比線程要出現(xiàn)得早,在1963年首次提出, 但沒(méi)有流行開(kāi)來(lái)。為什么沒(méi)有流行,沒(méi)有找到信服的資料,先挖個(gè)坑,以后那天了解后,再補(bǔ)上。

小結(jié)

進(jìn)程,線程,協(xié)程不斷突破,更高效的處理阻塞,不斷地提高CPU的利用率。但是并不是說(shuō),線程就一定比進(jìn)程快,而協(xié)程就一定不線程要快。具體還是要看應(yīng)用場(chǎng)景??梢院?jiǎn)單粗暴的把應(yīng)用分為IO密集型應(yīng)用以及CPU密集型應(yīng)用。

多核CPU,CPU密集型應(yīng)用
此時(shí)多線程的效率是最高的,多線程可以使到全部CPU核心滿載,又避免了協(xié)程間切換造成性能損失。當(dāng)CPU密集型任務(wù)時(shí),CPU一直在利用著,切換反而會(huì)造成性能損失,即便協(xié)程上下文切換消耗最小,但也還是有消耗的。

多核CPU,IO密集型應(yīng)用
此時(shí)采用多線程多協(xié)程效率最高,多線程可以使到全部CPU核心滿載,而一個(gè)線程多協(xié)程,則更好的提高了CPU的利用率。

單核CPU,CPU密集型應(yīng)用
單進(jìn)程效率是最高,此時(shí)單個(gè)進(jìn)程已經(jīng)使到CPU滿載了。

單核CPU,IO密集型應(yīng)用
多協(xié)程,效率最高。例如,看了上面應(yīng)該也是知道的了

并發(fā)與并行

并行

并行就是指同一時(shí)刻有兩個(gè)或兩個(gè)以上的“工作單位”在同時(shí)執(zhí)行,從硬件的角度上來(lái)看就是同一時(shí)刻有兩條或兩條以上的指令處于執(zhí)行階段。所以,多核是并行的前提,單線程永遠(yuǎn)無(wú)法達(dá)到并行狀態(tài)??梢岳枚嗑€程和度進(jìn)程到達(dá)并行狀態(tài)。另外的,Python的多線程由于GIL的存在,對(duì)于Python來(lái)說(shuō)無(wú)法通過(guò)多線程到達(dá)并行狀態(tài)。

并發(fā)

對(duì)于并發(fā)的理解,要從兩方面去理解,1.并發(fā)設(shè)計(jì) 2.并發(fā)執(zhí)行。先說(shuō)并發(fā)設(shè)計(jì),當(dāng)說(shuō)一個(gè)程序是并發(fā)的,更多的是指這個(gè)程序采取了并發(fā)設(shè)計(jì)。

并發(fā)設(shè)計(jì)的標(biāo)準(zhǔn):使多個(gè)操作可以在重疊的時(shí)間段內(nèi)進(jìn)行 ,這里的重點(diǎn)在于重疊的時(shí)間內(nèi), 重疊時(shí)間可以理解為一段時(shí)間內(nèi)。例如:在時(shí)間1s秒內(nèi), 具有IO操作的task1和task2都完成,這就可以說(shuō)是并發(fā)執(zhí)行。所以呢,單線程也是可以做到并發(fā)運(yùn)行的。當(dāng)然啦,并行肯定是并發(fā)的。一個(gè)程序能否并發(fā)執(zhí)行,取決于設(shè)計(jì),也取決于部署方式。例如, 當(dāng)給程序開(kāi)一個(gè)線程(協(xié)程是不開(kāi)的),它不可能是并發(fā)的,因?yàn)樵谥丿B時(shí)間內(nèi)根本就沒(méi)有兩個(gè)task在運(yùn)行。當(dāng)一個(gè)程序被設(shè)計(jì)成完成一個(gè)任務(wù)再去完成下一個(gè)任務(wù)的時(shí)候,即便部署是多線程多協(xié)程的也是無(wú)法達(dá)到并發(fā)運(yùn)行的。

并行與并發(fā)的關(guān)系: 并發(fā)的設(shè)計(jì)使到并發(fā)執(zhí)行成為可能,而并行是并發(fā)執(zhí)行的其中一種模式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容