進(jìn)程(process):
狹義定義:進(jìn)程就是一段程序的執(zhí)行過程例如啟動(dòng)的某個(gè)app悲敷。
廣義定義:進(jìn)程是一個(gè)具有獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動(dòng)究恤。它是操作系統(tǒng)動(dòng)態(tài)執(zhí)行的基本單元俭令,在傳統(tǒng)的操作系統(tǒng)中,進(jìn)程即是基本的分配單元后德,也是基本的執(zhí)行單元。
1)進(jìn)程是一個(gè)實(shí)體抄腔,每個(gè)進(jìn)程都有自己的地址空間瓢湃,一般情況下,包含文本區(qū)域赫蛇、數(shù)據(jù)區(qū)域绵患、堆棧
2)進(jìn)程是執(zhí)行中的程序,程序是一個(gè)沒有生命的實(shí)體悟耘,只有處理器賦予程序生命時(shí)落蝙,它才能成為一個(gè)活動(dòng)的實(shí)體,我們稱之為進(jìn)程
3)進(jìn)程本身不會(huì)運(yùn)行暂幼,是線程的容器筏勒。線程不能單獨(dú)執(zhí)行,必須組成進(jìn)程
4)一個(gè)程序至少有一個(gè)進(jìn)程旺嬉,一個(gè)進(jìn)程至少有一個(gè)線程
5)對于操作系統(tǒng)來講管行,一個(gè)任務(wù)就是一個(gè)進(jìn)程,比如開一個(gè)瀏覽器就是啟動(dòng)一個(gè)瀏覽器進(jìn)程邪媳。打開一款app就是打開一個(gè)進(jìn)程捐顷,例如打開香哈就是運(yùn)行了一個(gè)進(jìn)程。
6)有些進(jìn)程還不止同時(shí)做一件事情雨效。比如打開香哈迅涮,它可以同時(shí)進(jìn)行看視頻并且回復(fù)用戶評論,在一個(gè)進(jìn)程內(nèi)部徽龟,要同時(shí)干多件事情叮姑。
進(jìn)程狀態(tài):(三狀態(tài))
- 就緒:獲取出CPU外的所有資源、只要處理器分配資源就可以馬上執(zhí)行
- 運(yùn)行:獲得處理器分配的資源顿肺,程序開始執(zhí)行
- 阻塞:當(dāng)程序條件不夠的時(shí)候戏溺,需要等待提交滿足的時(shí)候才能執(zhí)行。
進(jìn)程狀態(tài):(五態(tài)模型)對于一個(gè)實(shí)際的系統(tǒng)屠尊,進(jìn)程的狀態(tài)及其轉(zhuǎn)換更為復(fù)雜旷祸。引入新建態(tài)和終止態(tài)構(gòu)成了進(jìn)程的五態(tài)模型。
- 創(chuàng)建狀態(tài):進(jìn)程在創(chuàng)建時(shí)需要申請一個(gè)空白PCB讼昆,向其中填寫控制和管理進(jìn)程的信息托享,完成資源分配。如果創(chuàng)建工作無法完成,比如資源無法滿足闰围,就無法被調(diào)度運(yùn)行赃绊,把此時(shí)進(jìn)程所處狀態(tài)稱為創(chuàng)建狀態(tài)
- 就緒狀態(tài):進(jìn)程已經(jīng)準(zhǔn)備好,已分配到所需資源羡榴,只要分配到CPU就能夠立即運(yùn)行
- 執(zhí)行狀態(tài):進(jìn)程處于就緒狀態(tài)被調(diào)度后碧查,進(jìn)程進(jìn)入執(zhí)行狀態(tài)
- 阻塞狀態(tài):正在執(zhí)行的進(jìn)程由于某些事件(I/O請求,申請緩存區(qū)失斝B亍)而暫時(shí)無法運(yùn)行忠售,進(jìn)程受到阻塞。在滿足請求時(shí)進(jìn)入就緒狀態(tài)等待系統(tǒng)調(diào)用
- 終止?fàn)顟B(tài):進(jìn)程結(jié)束迄沫,或出現(xiàn)錯(cuò)誤稻扬,或被系統(tǒng)終止,進(jìn)入終止?fàn)顟B(tài)羊瘩。無法再執(zhí)行
線程:
1)一個(gè)進(jìn)程中至少有一個(gè)線程泰佳,不然就沒有存在的意義
2)在一個(gè)進(jìn)程內(nèi)部,要同時(shí)干多件事情尘吗,就需要同時(shí)運(yùn)行多個(gè)子任務(wù)逝她,我們把進(jìn)程內(nèi)的這些子任務(wù)叫做線程
3)多線程就是為了同步完成多項(xiàng)任務(wù)(在單個(gè)程序中同時(shí)運(yùn)行多個(gè)線程完成不同的任務(wù)和工作),不是為了提高運(yùn)行效率摇予,而是為了提高資源使用效率來提高系統(tǒng)的效率
4)一個(gè)簡單的比喻汽绢,多線程就像是火車上的每節(jié)車廂,而進(jìn)程就是火車
5)線程是程序執(zhí)行流的最小單元侧戴。一個(gè)標(biāo)準(zhǔn)的線程由當(dāng)前的線程ID宁昭、當(dāng)前指令指針、寄存器和堆棧組成
6)同一個(gè)進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行
線程狀態(tài):
1)就緒:指線程具備運(yùn)行的所有條件酗宋,邏輯上可以運(yùn)行积仗,在等待處理機(jī)
2)運(yùn)行:指線程占用處理機(jī)正在運(yùn)行
3)阻塞:線程在等待一個(gè)事件,邏輯上不可執(zhí)行
如果我們要同時(shí)執(zhí)行多個(gè)任務(wù)怎么辦蜕猫?
1)啟動(dòng)多個(gè)進(jìn)程寂曹,每個(gè)進(jìn)程雖然只有一個(gè)線程,但是多個(gè)進(jìn)程可以一塊執(zhí)行多個(gè)任務(wù)
2)啟動(dòng)一個(gè)進(jìn)程回右,在一個(gè)進(jìn)程內(nèi)啟動(dòng)多個(gè)線程隆圆,這樣多個(gè)線程也可以一塊執(zhí)行多個(gè)任務(wù)
多任務(wù):
1)一邊瀏覽網(wǎng)頁、一邊聽歌翔烁、一邊看電影渺氧;這就是多任務(wù)。
協(xié)程:
協(xié)程是一種用戶態(tài)的輕量級(jí)線程蹬屹,協(xié)程的調(diào)度完全由用戶控制(進(jìn)程和線程都是由cpu 內(nèi)核進(jìn)行調(diào)度)侣背。協(xié)程擁有自己的寄存器上下文和棧白华。協(xié)程調(diào)度切換時(shí),將寄存器上下文和棧保存到其他地方贩耐,在切回來的時(shí)候弧腥,恢復(fù)先前保存的寄存器上下文和棧,直接操作棧則基本沒有內(nèi)核切換的開銷潮太,可以不加鎖的訪問全局變量管搪,所以上下文的切換非常快消别。
對于 進(jìn)程抛蚤、線程,都是有內(nèi)核進(jìn)行調(diào)度寻狂,有 CPU 時(shí)間片的概念,進(jìn)行 搶占式調(diào)度(有多種調(diào)度算法)
對于 協(xié)程(用戶級(jí)線程)朋沮,這是對內(nèi)核透明的蛇券,也就是系統(tǒng)并不知道有協(xié)程的存在,是完全由用戶自己的程序進(jìn)行調(diào)度的樊拓,因?yàn)槭怯捎脩舫绦蜃约嚎刂凭姥牵敲淳秃茈y像搶占式調(diào)度那樣做到強(qiáng)制的 CPU 控制權(quán)切換到其他進(jìn)程/線程,通常只能進(jìn)行 協(xié)作式調(diào)度筋夏,需要協(xié)程自己主動(dòng)把控制權(quán)轉(zhuǎn)讓出去之后蒂胞,其他協(xié)程才能被執(zhí)行到。
goroutine 和協(xié)程區(qū)別
本質(zhì)上条篷,goroutine 就是協(xié)程骗随。 不同的是,Golang 在 runtime赴叹、系統(tǒng)調(diào)用等多方面對 goroutine 調(diào)度進(jìn)行了封裝和處理鸿染,當(dāng)遇到長時(shí)間執(zhí)行或者進(jìn)行系統(tǒng)調(diào)用時(shí),會(huì)主動(dòng)把當(dāng)前 goroutine 的CPU (P) 轉(zhuǎn)讓出去乞巧,讓其他 goroutine 能被調(diào)度并執(zhí)行涨椒,也就是 Golang 從語言層面支持了協(xié)程。Golang 的一大特色就是從語言層面原生支持協(xié)程绽媒,在函數(shù)或者方法前面加 go關(guān)鍵字就可創(chuàng)建一個(gè)協(xié)程蚕冬。
其他方面的比較
內(nèi)存消耗方面
每個(gè) goroutine (協(xié)程) 默認(rèn)占用內(nèi)存遠(yuǎn)比 Java 、C 的線程少是辕。
goroutine:2KB(官方)
線程:8MB(參考網(wǎng)絡(luò))線程和 goroutine 切換調(diào)度開銷方面
線程/goroutine 切換開銷方面囤热,goroutine 遠(yuǎn)比線程小
線程:涉及模式切換(從用戶態(tài)切換到內(nèi)核態(tài))、16個(gè)寄存器免糕、PC赢乓、SP...等寄存器的刷新等忧侧。
goroutine:只有三個(gè)寄存器的值修改 - PC / SP / DX.