本篇內(nèi)容介紹了“協(xié)程和線程的區(qū)別和聯(lián)系”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)公司:于2013年開始為各行業(yè)開拓出企業(yè)自己的“網(wǎng)站建設(shè)”服務(wù),為近1000家公司企業(yè)提供了專業(yè)的網(wǎng)站設(shè)計制作、成都網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計和網(wǎng)站推廣服務(wù), 按需設(shè)計網(wǎng)站由設(shè)計師親自精心設(shè)計,設(shè)計的效果完全按照客戶的要求,并適當?shù)奶岢龊侠淼慕ㄗh,擁有的視覺效果,策劃師分析客戶的同行競爭對手,根據(jù)客戶的實際情況給出合理的網(wǎng)站構(gòu)架,制作客戶同行業(yè)具有領(lǐng)先地位的。
進程是操作系統(tǒng)對一個正在運行的程序的一種抽象,進程是資源分配的最小單位。
進程在操作系統(tǒng)中的抽象表現(xiàn)
為什么會有 ”進程“ 呢?說白了還是為了合理壓榨 CPU 的性能和分配運行的時間片,不能 “閑著“。
在計算機中,其計算核心是 CPU,負責所有計算相關(guān)的工作和資源。單個 CPU 一次只能運行一個任務(wù)。如果一個進程跑著,就把唯一一個 CPU 給完全占住,那是非常不合理的。
那為什么要壓榨 CPU 的性能?因為 CPU 實在是太快,太快,太快了,寄存器僅僅能夠追的上他的腳步,RAM 和別的掛在各總線上的設(shè)備則更是望塵莫及。
如果總是在運行一個進程上的任務(wù),就會出現(xiàn)一個現(xiàn)象。就是任務(wù)不一定總是在執(zhí)行 ”計算型“ 的任務(wù),會有很大可能是在執(zhí)行網(wǎng)絡(luò)調(diào)用,阻塞了,CPU 豈不就浪費了?
進程的上下文切換
這又出現(xiàn)了多進程,多個 CPU,多個進程。多進程就是指計算機系統(tǒng)可以同時執(zhí)行多個進程,從一個進程到另外一個進程的轉(zhuǎn)換是由操作系統(tǒng)內(nèi)核管理的,一般是同時運行多個軟件。
有了多進程,想必在操作系統(tǒng)上可以同時運行多個進程。那么為什么有了進程,還要線程呢?
原因如下:
進程間的信息難以共享數(shù)據(jù),父子進程并未共享內(nèi)存,需要通過進程間通信(IPC),在進程間進行信息交換,性能開銷較大。
創(chuàng)建進程(一般是調(diào)用 fork 方法)的性能開銷較大。
大家又把目光轉(zhuǎn)向了進程內(nèi),能不能在進程里做點什么呢?
進程由多個線程組成
一個進程可以由多個稱為線程的執(zhí)行單元組成。每個線程都運行在進程的上下文中,共享著同樣的代碼和全局數(shù)據(jù)。
多個進程,就可以有更多的線程。多線程比多進程之間更容易共享數(shù)據(jù),在上下文切換中線程一般比進程更高效。
原因如下:
線程之間能夠非常方便、快速地共享數(shù)據(jù)。
只需將數(shù)據(jù)復(fù)制到進程中的共享區(qū)域就可以了,但需要注意避免多個線程修改同一份內(nèi)存。
創(chuàng)建線程比創(chuàng)建進程要快 10 倍甚至更多。
線程都是同一個進程下自家的孩子,像是內(nèi)存頁、頁表等就不需要了。
協(xié)程(Coroutine)是用戶態(tài)的線程。通常創(chuàng)建協(xié)程時,會從進程的堆中分配一段內(nèi)存作為協(xié)程的棧。
線程的棧有 8 MB,而協(xié)程棧的大小通常只有 KB,而 Go 語言的協(xié)程更夸張,只有 2-4KB,非常的輕巧。
根據(jù)維基百科的說法,馬爾文·康威于 1958 年發(fā)明了術(shù)語 “coroutine” 并用于構(gòu)建匯編程序,關(guān)于協(xié)程最初的出版解說在 1963 年發(fā)表。
也就是歷史上是先有的 “協(xié)程”,再有的 “線程”,線程是在在協(xié)程的基礎(chǔ)上添加了棧等功能后擴展出來的。
但為什么一開始協(xié)程沒有火起來呢?這個比較難考證,大概率還是與 60 年前的計算機時代背景有關(guān)。
而如今人們把協(xié)程調(diào)度的邏輯更進一步抽象為 “等 IO,讓出,IO 完畢”,在此基礎(chǔ)上人們發(fā)現(xiàn)協(xié)程的方式能解決多線程環(huán)境下很多代碼邏輯 “混亂”。
既然線程似乎已經(jīng)很好地填補了進程的遺憾,那怎么又出來了一個 “協(xié)程”,難道是重復(fù)造輪子嗎?
協(xié)程的優(yōu)勢(via InfoQ @八兩)如下:
節(jié)省 CPU:避免系統(tǒng)內(nèi)核級的線程頻繁切換,造成的 CPU 資源浪費。好鋼用在刀刃上。而協(xié)程是用戶態(tài)的線程,用戶可以自行控制協(xié)程的創(chuàng)建于銷毀,極大程度避免了系統(tǒng)級線程上下文切換造成的資源浪費。
節(jié)約內(nèi)存:在 64 位的Linux中,一個線程需要分配 8MB 棧內(nèi)存和 64MB 堆內(nèi)存,系統(tǒng)內(nèi)存的制約導(dǎo)致我們無法開啟更多線程實現(xiàn)高并發(fā)。而在協(xié)程編程模式下,可以輕松有十幾萬協(xié)程,這是線程無法比擬的。
穩(wěn)定性:前面提到線程之間通過內(nèi)存來共享數(shù)據(jù),這也導(dǎo)致了一個問題,任何一個線程出錯時,進程中的所有線程都會跟著一起崩潰。
開發(fā)效率:使用協(xié)程在開發(fā)程序之中,可以很方便的將一些耗時的IO操作異步化,例如寫文件、耗時 IO 請求等。
協(xié)程本質(zhì)上就是用戶態(tài)下的線程,所以也有人說協(xié)程是 “輕線程”,但我們一定要區(qū)分用戶態(tài)和內(nèi)核態(tài)的區(qū)別,很關(guān)鍵。
歸歸根到底,在日?;蛎嬖囍杏龅?“什么是協(xié)程,協(xié)程和線程的區(qū)別和聯(lián)系?” 這類問題時,面試者常規(guī)會把進程、線程、協(xié)程都介紹一遍。
為了方便記憶和詮釋,推薦大家結(jié)合故事來講會比較好,這一塊可以參考阮一峰大神翻譯的《進程與線程的一個簡單解釋》,會帶來不少好感。
而最關(guān)鍵的部分,在于協(xié)程和線程的區(qū)別和聯(lián)系是什么?
我們可以通過文章中的介紹,從協(xié)程 -> 線程的歷史進程來說明。接著進一步對比協(xié)程和線程兩者的優(yōu)勢和缺點,就能比較好的詮釋區(qū)別和聯(lián)系了。
更優(yōu)秀的部分,可以詮釋完基本概念和區(qū)別后,進一步延伸都你所面試的崗位,例如是 Go 語言,就可以介紹 Go 語言的協(xié)程的具體應(yīng)用和實現(xiàn)。
畢竟,Go 語言可以輕輕松松開數(shù)十萬個協(xié)程,毫無波瀾。這樣能夠更好的體現(xiàn)你對協(xié)程、線程的知識深度和廣度應(yīng)用,而不是單純的背概念。
參考
線程和進程的區(qū)別是什么?
有了多線程,為什么還要有協(xié)程?
進程與線程的一個簡單解釋
“協(xié)程和線程的區(qū)別和聯(lián)系”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!