進程與線程之間根本性的區(qū)別

進程

我們編寫的代碼只是一個存儲在硬盤的靜態(tài)文件起意,通過編譯后就會生成二進制可執(zhí)行文件,當(dāng)我們運行這個可執(zhí)行文件后病瞳,它會被裝載到內(nèi)存中揽咕,接著 CPU 會執(zhí)行程序中的每一條指令悲酷,那么這個運行中的程序,就被稱為「進程」心褐。

現(xiàn)在我們考慮有一個會讀取硬盤文件數(shù)據(jù)的程序被執(zhí)行了舔涎,那么當(dāng)運行到讀取文件的指令時,就會去從硬盤讀取數(shù)據(jù)逗爹,但是硬盤的讀寫速度是非常慢的,那么在這個時候嚎于,如果 CPU 傻傻的等硬盤返回數(shù)據(jù)的話掘而,那 CPU 的利用率是非常低的。

做個類比于购,你去煮開水時袍睡,你會傻傻的等水壺?zé)_嗎?很明顯肋僧,小孩也不會傻等斑胜。我們可以在水壺?zé)_之前去做其他事情。當(dāng)水壺?zé)_了嫌吠,我們自然就會聽到“嘀嘀嘀”的聲音止潘,于是再把燒開的水倒入到水杯里就好了。

所以辫诅,當(dāng)進程要從硬盤讀取數(shù)據(jù)時凭戴,CPU 不需要阻塞等待數(shù)據(jù)的返回,而是去執(zhí)行另外的進程炕矮。當(dāng)硬盤數(shù)據(jù)返回時么夫,CPU 會收到個中斷,于是 CPU 再繼續(xù)運行這個進程肤视。


這種多個程序档痪、交替執(zhí)行的思想,就有 CPU 管理多個進程的初步想法邢滑。

對于一個支持多進程的系統(tǒng)腐螟,CPU 會從一個進程快速切換至另一個進程,其間每個進程各運行幾十或幾百個毫秒殊鞭。

雖然單核的 CPU 在某一個瞬間遭垛,只能運行一個進程。但在 1 秒鐘期間操灿,它可能會運行多個進程锯仪,這樣就產(chǎn)生并行的錯覺,實際上這是并發(fā)趾盐。

并發(fā)和并行有什么區(qū)別庶喜?

一圖勝千言小腊。


進程與程序的關(guān)系的類比

到了晚飯時間,一對小情侶肚子都咕咕叫了久窟,于是男生見機行事秩冈,就想給女生做晚飯,所以他就在網(wǎng)上找了辣子雞的菜譜斥扛,接著買了一些雞肉入问、辣椒、香料等材料稀颁,然后邊看邊學(xué)邊做這道菜芬失。


突然,女生說她想喝可樂匾灶,那么男生只好把做菜的事情暫停一下棱烂,并在手機菜譜標(biāo)記做到哪一個步驟,把狀態(tài)信息記錄了下來阶女。

然后男生聽從女生的指令颊糜,跑去下樓買了一瓶冰可樂后,又回到廚房繼續(xù)做菜秃踩。

這體現(xiàn)了衬鱼,CPU 可以從一個進程(做菜)切換到另外一個進程(買可樂),在切換前必須要記錄當(dāng)前進程中運行的狀態(tài)信息吞瞪,以備下次切換回來的時候可以恢復(fù)執(zhí)行馁启。

所以,可以發(fā)現(xiàn)進程有著「運行 - 暫停 - 運行」的活動規(guī)律芍秆。

進程的狀態(tài)

在上面惯疙,我們知道了進程有著「運行 - 暫停 - 運行」的活動規(guī)律。一般說來妖啥,一個進程并不是自始至終連續(xù)不停地運行的霉颠,它與并發(fā)執(zhí)行中的其他進程的執(zhí)行是相互制約的。

它有時處于運行狀態(tài)荆虱,有時又由于某種原因而暫停運行處于等待狀態(tài)蒿偎,當(dāng)使它暫停的原因消失后,它又進入準(zhǔn)備運行狀態(tài)怀读。

所以诉位,在一個進程的活動期間至少具備三種基本狀態(tài),即運行狀態(tài)菜枷、就緒狀態(tài)苍糠、阻塞狀態(tài)。

上圖中各個狀態(tài)的意義:

運行狀態(tài)(Runing):該時刻進程占用 CPU啤誊;

就緒狀態(tài)(Ready):可運行岳瞭,但因為其他進程正在運行而暫停停止拥娄;

阻塞狀態(tài)(Blocked):該進程正在等待某一事件發(fā)生(如等待輸入/輸出操作的完成)而暫時停止運行,這時瞳筏,即使給它CPU控制權(quán)稚瘾,它也無法運行;

當(dāng)然姚炕,進程另外兩個基本狀態(tài):

創(chuàng)建狀態(tài)(new):進程正在被創(chuàng)建時的狀態(tài)摊欠;

結(jié)束狀態(tài)(Exit):進程正在從系統(tǒng)中消失時的狀態(tài);

于是柱宦,一個完整的進程狀態(tài)的變遷如下圖:


再來詳細(xì)說明一下進程的狀態(tài)變遷:

NULL -> 創(chuàng)建狀態(tài):一個新進程被創(chuàng)建時的第一個狀態(tài)凄硼;

創(chuàng)建狀態(tài) -> 就緒狀態(tài):當(dāng)進程被創(chuàng)建完成并初始化后,一切就緒準(zhǔn)備運行時捷沸,變?yōu)榫途w狀態(tài),這個過程是很快的狐史;

就緒態(tài) -> 運行狀態(tài):處于就緒狀態(tài)的進程被操作系統(tǒng)的進程調(diào)度器選中后痒给,就分配給 CPU 正式運行該進程;

運行狀態(tài) -> 結(jié)束狀態(tài):當(dāng)進程已經(jīng)運行完成或出錯時骏全,會被操作系統(tǒng)作結(jié)束狀態(tài)處理苍柏;

運行狀態(tài) -> 就緒狀態(tài):處于運行狀態(tài)的進程在運行過程中,由于分配給它的運行時間片用完姜贡,操作系統(tǒng)會把該進程變?yōu)榫途w態(tài)试吁,接著從就緒態(tài)選中另外一個進程運行;

運行狀態(tài) -> 阻塞狀態(tài):當(dāng)進程請求某個事件且必須等待時楼咳,例如請求 I/O 事件熄捍;

阻塞狀態(tài) -> 就緒狀態(tài):當(dāng)進程要等待的事件完成時,它從阻塞狀態(tài)變到就緒狀態(tài)母怜;

如果有大量處于阻塞狀態(tài)的進程余耽,進程可能會占用著物理內(nèi)存空間,顯然不是我們所希望的苹熏,畢竟物理內(nèi)存空間是有限的碟贾,被阻塞狀態(tài)的進程占用著物理內(nèi)存就一種浪費物理內(nèi)存的行為。

所以轨域,在虛擬內(nèi)存管理的操作系統(tǒng)中袱耽,通常會把阻塞狀態(tài)的進程的物理內(nèi)存空間換出到硬盤,等需要再次運行的時候干发,再從硬盤換入到物理內(nèi)存朱巨。


那么,就需要一個新的狀態(tài)铐然,來描述進程沒有占用實際的物理內(nèi)存空間的情況蔬崩,這個狀態(tài)就是掛起狀態(tài)恶座。這跟阻塞狀態(tài)是不一樣,阻塞狀態(tài)是等待某個事件的返回沥阳。

另外跨琳,掛起狀態(tài)可以分為兩種:

阻塞掛起狀態(tài):進程在外存(硬盤)并等待某個事件的出現(xiàn);

就緒掛起狀態(tài):進程在外存(硬盤)桐罕,但只要進入內(nèi)存脉让,即刻立刻運行;

這兩種掛起狀態(tài)加上前面的五種狀態(tài)功炮,就變成了七種狀態(tài)變遷(留給我的顏色不多了)溅潜,見如下圖:


導(dǎo)致進程掛起的原因不只是因為進程所使用的內(nèi)存空間不在物理內(nèi)存,還包括如下情況:

通過 sleep 讓進程間歇性掛起薪伏,其工作原理是設(shè)置一個定時器滚澜,到期后喚醒進程。

用戶希望掛起一個程序的執(zhí)行嫁怀,比如在 Linux 中用Ctrl+Z掛起進程设捐;

進程的控制結(jié)構(gòu)

在操作系統(tǒng)中,是用進程控制塊process control block塘淑,PCB)數(shù)據(jù)結(jié)構(gòu)來描述進程的萝招。

那 PCB 是什么呢?打開知乎搜索你就會發(fā)現(xiàn)這個東西并不是那么簡單存捺。


打住打住槐沼,我們是個正經(jīng)的人,怎么會去看那些問題呢捌治?是吧岗钩,回來回來。

PCB 是進程存在的唯一標(biāo)識具滴,這意味著一個進程的存在凹嘲,必然會有一個 PCB,如果進程消失了构韵,那么 PCB 也會隨之消失周蹭。

PCB 具體包含什么信息呢?

進程描述信息:

進程標(biāo)識符:標(biāo)識各個進程疲恢,每個進程都有一個并且唯一的標(biāo)識符凶朗;

用戶標(biāo)識符:進程歸屬的用戶,用戶標(biāo)識符主要為共享和保護服務(wù)显拳;

進程控制和管理信息:

進程當(dāng)前狀態(tài)棚愤,如 new、ready、running宛畦、waiting 或 blocked 等瘸洛;

進程優(yōu)先級:進程搶占 CPU 時的優(yōu)先級;

資源分配清單:

有關(guān)內(nèi)存地址空間或虛擬地址空間的信息次和,所打開文件的列表和所使用的 I/O 設(shè)備信息反肋。

CPU 相關(guān)信息:

CPU 中各個寄存器的值,當(dāng)進程被切換時踏施,CPU 的狀態(tài)信息都會被保存在相應(yīng)的 PCB 中石蔗,以便進程重新執(zhí)行時,能從斷點處繼續(xù)執(zhí)行畅形。

可見养距,PCB 包含信息還是比較多的。

每個 PCB 是如何組織的呢日熬?

通常是通過鏈表的方式進行組織棍厌,把具有相同狀態(tài)的進程鏈在一起,組成各種隊列竖席。比如:

將所有處于就緒狀態(tài)的進程鏈在一起定铜,稱為就緒隊列

把所有因等待某事件而處于等待狀態(tài)的進程鏈在一起就組成各種阻塞隊列怕敬;

另外,對于運行隊列在單核 CPU 系統(tǒng)中則只有一個運行指針了帘皿,因為單核 CPU 在某個時間东跪,只能運行一個程序。

那么鹰溜,就緒隊列和阻塞隊列鏈表的組織形式如下圖:


除了鏈接的組織方式虽填,還有索引方式,它的工作原理:將同一狀態(tài)的進程組織在一個索引表中彬伦,索引表項指向相應(yīng)的 PCB涂屁,不同狀態(tài)對應(yīng)不同的索引表林艘。

一般會選擇鏈表,因為可能面臨進程創(chuàng)建恶守,銷毀等調(diào)度導(dǎo)致進程狀態(tài)發(fā)生變化,所以鏈表能夠更加靈活的插入和刪除贡必。

進程的控制

我們熟知了進程的狀態(tài)變遷和進程的數(shù)據(jù)結(jié)構(gòu) PCB 后兔港,再來看看進程的創(chuàng)建、終止仔拟、阻塞衫樊、喚醒的過程,這些過程也就是進程的控制。

01 創(chuàng)建進程

操作系統(tǒng)允許一個進程創(chuàng)建另一個進程科侈,而且允許子進程繼承父進程所擁有的資源载佳,當(dāng)子進程被終止時,其在父進程處繼承的資源應(yīng)當(dāng)還給父進程臀栈。同時蔫慧,終止父進程時同時也會終止其所有的子進程。

創(chuàng)建進程的過程如下:

為新進程分配一個唯一的進程標(biāo)識號挂脑,并申請一個空白的 PCB藕漱,PCB 是有限的,若申請失敗則創(chuàng)建失斦赶小肋联;

為進程分配資源,此處如果資源不足刁俭,進程就會進入等待狀態(tài)橄仍,以等待資源;

初始化PCB牍戚;

如果進程的調(diào)度隊列能夠接納新進程侮繁,那就將進程插入到就緒隊列,等待被調(diào)度運行如孝;

02 終止進程

進程可以有 3 種終止方式:正常結(jié)束宪哩、異常結(jié)束以及外界干預(yù)(信號kill掉)。

終止進程的過程如下:

查找需要終止的進程的 PCB第晰;

如果處于執(zhí)行狀態(tài)锁孟,則立即終止該進程的執(zhí)行,然后將 CPU 資源分配給其他進程茁瘦;

如果其還有子進程品抽,則應(yīng)將其所有子進程終止;

將該進程所擁有的全部資源都?xì)w還給父進程或操作系統(tǒng)甜熔;

將其從 PCB 所在隊列中刪除圆恤;

03 阻塞進程

當(dāng)進程需要等待某一事件完成時,它可以調(diào)用阻塞語句把自己阻塞等待腔稀。而一旦被阻塞等待盆昙,它只能由另一個進程喚醒。

阻塞進程的過程如下:

找到將要被阻塞進程標(biāo)識號對應(yīng)的 PCB焊虏;

如果該進程為運行狀態(tài)弱左,則保護其現(xiàn)場,將其狀態(tài)轉(zhuǎn)為阻塞狀態(tài)炕淮,停止運行拆火;

將該 PCB 插入的阻塞隊列中去;

04 喚醒進程

進程由「運行」轉(zhuǎn)變?yōu)椤缸枞範(fàn)顟B(tài)是由于進程必須等待某一事件的完成,所以處于阻塞狀態(tài)的進程是絕對不可能叫醒自己的们镜。

如果某進程正在等待 I/O 事件币叹,需由別的進程發(fā)消息給它,則只有當(dāng)該進程所期待的事件出現(xiàn)時模狭,才由發(fā)現(xiàn)者進程用喚醒語句叫醒它颈抚。

喚醒進程的過程如下:

在該事件的阻塞隊列中找到相應(yīng)進程的 PCB;

將其從阻塞隊列中移出嚼鹉,并置其狀態(tài)為就緒狀態(tài)贩汉;

把該 PCB 插入到就緒隊列中,等待調(diào)度程序調(diào)度锚赤;

進程的阻塞和喚醒是一對功能相反的語句匹舞,如果某個進程調(diào)用了阻塞語句,則必有一個與之對應(yīng)的喚醒語句线脚。

進程的上下文切換

各個進程之間是共享 CPU 資源的赐稽,在不同的時候進程之間需要切換,讓不同的進程可以在 CPU 執(zhí)行浑侥,那么這個一個進程切換到另一個進程運行姊舵,稱為進程的上下文切換

在詳細(xì)說進程上下文切換前寓落,我們先來看看 CPU 上下文切換

大多數(shù)操作系統(tǒng)都是多任務(wù)括丁,通常支持大于 CPU 數(shù)量的任務(wù)同時運行。實際上伶选,這些任務(wù)并不是同時運行的躏将,只是因為系統(tǒng)在很短的時間內(nèi),讓各個任務(wù)分別在 CPU 運行考蕾,于是就造成同時運行的錯覺。

任務(wù)是交給 CPU 運行的会宪,那么在每個任務(wù)運行前肖卧,CPU 需要知道任務(wù)從哪里加載,又從哪里開始運行掸鹅。

所以塞帐,操作系統(tǒng)需要事先幫 CPU 設(shè)置好CPU 寄存器和程序計數(shù)器

CPU 寄存器是 CPU 內(nèi)部一個容量小巍沙,但是速度極快的內(nèi)存(緩存)葵姥。我舉個例子,寄存器像是你的口袋句携,內(nèi)存像你的書包榔幸,硬盤則是你家里的柜子,如果你的東西存放到口袋,那肯定是比你從書包或家里柜子取出來要快的多削咆。

再來牍疏,程序計數(shù)器則是用來存儲 CPU 正在執(zhí)行的指令位置、或者即將執(zhí)行的下一條指令位置拨齐。

所以說鳞陨,CPU 寄存器和程序計數(shù)是 CPU 在運行任何任務(wù)前歼狼,所必須依賴的環(huán)境,這些環(huán)境就叫做CPU 上下文

既然知道了什么是 CPU 上下文凿滤,那理解 CPU 上下文切換就不難了。

CPU 上下文切換就是先把前一個任務(wù)的 CPU 上下文(CPU 寄存器和程序計數(shù)器)保存起來枫疆,然后加載新任務(wù)的上下文到這些寄存器和程序計數(shù)器,最后再跳轉(zhuǎn)到程序計數(shù)器所指的新位置拯啦,運行新任務(wù)兵迅。

系統(tǒng)內(nèi)核會存儲保持下來的上下文信息交洗,當(dāng)此任務(wù)再次被分配給 CPU 運行時,CPU 會重新加載這些上下文,這樣就能保證任務(wù)原來的狀態(tài)不受影響缕贡,讓任務(wù)看起來還是連續(xù)運行。

上面說到所謂的「任務(wù)」,主要包含進程谍倦、線程和中斷。所以阐斜,可以根據(jù)任務(wù)的不同,把 CPU 上下文切換分成:進程上下文切換邻奠、線程上下文切換和中斷上下文切換笤喳。

進程的上下文切換到底是切換什么呢?

進程是由內(nèi)核管理和調(diào)度的碌宴,所以進程的切換只能發(fā)生在內(nèi)核態(tài)杀狡。

所以,進程的上下文切換不僅包含了虛擬內(nèi)存贰镣、棧呜象、全局變量等用戶空間的資源膳凝,還包括了內(nèi)核堆棧、寄存器等內(nèi)核空間的資源恭陡。

通常蹬音,會把交換的信息保存在進程的 PCB,當(dāng)要運行另外一個進程的時候休玩,我們需要從這個進程的 PCB 取出上下文著淆,然后恢復(fù)到 CPU 中,這使得這個進程可以繼續(xù)執(zhí)行哥捕,如下圖所示:


大家需要注意牧抽,進程的上下文開銷是很關(guān)鍵的,我們希望它的開銷越小越好遥赚,這樣可以使得進程可以把更多時間花費在執(zhí)行程序上扬舒,而不是耗費在上下文切換。

發(fā)生進程上下文切換有哪些場景凫佛?

為了保證所有進程可以得到公平調(diào)度讲坎,CPU 時間被劃分為一段段的時間片,這些時間片再被輪流分配給各個進程愧薛。這樣晨炕,當(dāng)某個進程的時間片耗盡了,進程就從運行狀態(tài)變?yōu)榫途w狀態(tài)毫炉,系統(tǒng)從就緒隊列選擇另外一個進程運行瓮栗;

進程在系統(tǒng)資源不足(比如內(nèi)存不足)時,要等到資源滿足后才可以運行瞄勾,這個時候進程也會被掛起费奸,并由系統(tǒng)調(diào)度其他進程運行;

當(dāng)進程通過睡眠函數(shù) sleep 這樣的方法將自己主動掛起時进陡,自然也會重新調(diào)度愿阐;

當(dāng)有優(yōu)先級更高的進程運行時,為了保證高優(yōu)先級進程的運行趾疚,當(dāng)前進程會被掛起缨历,由高優(yōu)先級進程來運行;

發(fā)生硬件中斷時糙麦,CPU 上的進程會被中斷掛起辛孵,轉(zhuǎn)而執(zhí)行內(nèi)核中的中斷服務(wù)程序;

以上赡磅,就是發(fā)生進程上下文切換的常見場景了魄缚。

線程

在早期的操作系統(tǒng)中都是以進程作為獨立運行的基本單位,直到后面仆邓,計算機科學(xué)家們又提出了更小的能獨立運行的基本單位鲜滩,也就是線程。

為什么使用線程节值?

我們舉個例子徙硅,假設(shè)你要編寫一個視頻播放器軟件,那么該軟件功能的核心模塊有三個:

從視頻文件當(dāng)中讀取數(shù)據(jù)搞疗;

對讀取的數(shù)據(jù)進行解壓縮嗓蘑;

把解壓縮后的視頻數(shù)據(jù)播放出來;

對于單進程的實現(xiàn)方式匿乃,我想大家都會是以下這個方式:


對于單進程的這種方式桩皿,存在以下問題:

播放出來的畫面和聲音會不連貫,因為當(dāng) CPU 能力不夠強的時候幢炸,Read?的時候可能進程就等在這了泄隔,這樣就會導(dǎo)致等半天才進行數(shù)據(jù)解壓和播放;

各個函數(shù)之間不是并發(fā)執(zhí)行宛徊,影響資源的使用效率佛嬉;

那改進成多進程的方式:


對于多進程的這種方式,依然會存在問題:

進程之間如何通信闸天,共享數(shù)據(jù)暖呕?

維護進程的系統(tǒng)開銷較大,如創(chuàng)建進程時苞氮,分配資源湾揽、建立 PCB;終止進程時笼吟,回收資源库物、撤銷 PCB;進程切換時赞厕,保存當(dāng)前進程的狀態(tài)信息艳狐;

那到底如何解決呢?需要有一種新的實體皿桑,滿足以下特性:

實體之間可以并發(fā)運行毫目;

實體之間共享相同的地址空間;

這個新的實體诲侮,就是線程(Thread)镀虐,線程之間可以并發(fā)運行且共享相同的地址空間。

什么是線程沟绪?

線程是進程當(dāng)中的一條執(zhí)行流程刮便。

同一個進程內(nèi)多個線程之間可以共享代碼段、數(shù)據(jù)段绽慈、打開的文件等資源恨旱,但每個線程都有獨立一套的寄存器和棧辈毯,這樣可以確保線程的控制流是相對獨立的。


線程的優(yōu)缺點搜贤?

線程的優(yōu)點:

一個進程中可以同時存在多個線程谆沃;

各個線程之間可以并發(fā)執(zhí)行;

各個線程之間可以共享地址空間和文件等資源仪芒;

線程的缺點:

當(dāng)進程中的一個線程奔潰時唁影,會導(dǎo)致其所屬進程的所有線程奔潰。

舉個例子掂名,對于游戲的用戶設(shè)計据沈,則不應(yīng)該使用多線程的方式,否則一個用戶掛了饺蔑,會影響其他同個進程的線程锌介。

線程與進程的比較

線程與進程的比較如下:

進程是資源(包括內(nèi)存、打開的文件等)分配的單位猾警,線程是 CPU 調(diào)度的單位掏湾;

進程擁有一個完整的資源平臺,而線程只獨享必不可少的資源肿嘲,如寄存器和棧融击;

線程同樣具有就緒、阻塞雳窟、執(zhí)行三種基本狀態(tài)尊浪,同樣具有狀態(tài)之間的轉(zhuǎn)換關(guān)系;

線程能減少并發(fā)執(zhí)行的時間和空間開銷封救;

對于拇涤,線程相比進程能減少開銷,體現(xiàn)在:

線程的創(chuàng)建時間比進程快誉结,因為進程在創(chuàng)建的過程中鹅士,還需要資源管理信息,比如內(nèi)存管理信息惩坑、文件管理信息掉盅,而線程在創(chuàng)建的過程中,不會涉及這些資源管理信息以舒,而是共享它們趾痘;

線程的終止時間比進程快,因為線程釋放的資源相比進程少很多蔓钟;

同一個進程內(nèi)的線程切換比進程切換快永票,因為線程具有相同的地址空間(虛擬內(nèi)存共享),這意味著同一個進程的線程都具有同一個頁表,那么在切換的時候不需要切換頁表侣集。而對于進程之間的切換键俱,切換的時候要把頁表給切換掉,而頁表的切換過程開銷是比較大的世分;

由于同一進程的各線程間共享內(nèi)存和文件資源方妖,那么在線程之間數(shù)據(jù)傳遞的時候,就不需要經(jīng)過內(nèi)核了罚攀,這就使得線程之間的數(shù)據(jù)交互效率更高了;

所以雌澄,線程比進程不管是時間效率斋泄,還是空間效率都要高。

線程的上下文切換

在前面我們知道了镐牺,線程與進程最大的區(qū)別在于:線程是調(diào)度的基本單位炫掐,而進程則是資源擁有的基本單位

所以睬涧,所謂操作系統(tǒng)的任務(wù)調(diào)度募胃,實際上的調(diào)度對象是線程,而進程只是給線程提供了虛擬內(nèi)存畦浓、全局變量等資源痹束。

對于線程和進程,我們可以這么理解:

當(dāng)進程只有一個線程時讶请,可以認(rèn)為進程就等于線程祷嘶;

當(dāng)進程擁有多個線程時,這些線程會共享相同的虛擬內(nèi)存和全局變量等資源夺溢,這些資源在上下文切換時是不需要修改的论巍;

另外,線程也有自己的私有數(shù)據(jù)风响,比如棧和寄存器等嘉汰,這些在上下文切換時也是需要保存的。

線程上下文切換的是什么状勤?

這還得看線程是不是屬于同一個進程:

當(dāng)兩個線程不是屬于同一個進程鞋怀,則切換的過程就跟進程上下文切換一樣;

當(dāng)兩個線程是屬于同一個進程持搜,因為虛擬內(nèi)存是共享的接箫,所以在切換時,虛擬內(nèi)存這些資源就保持不動朵诫,只需要切換線程的私有數(shù)據(jù)辛友、寄存器等不共享的數(shù)據(jù)

所以,線程的上下文切換相比進程废累,開銷要小很多邓梅。

線程的實現(xiàn)

主要有三種線程的實現(xiàn)方式:

用戶線程(User Thread:在用戶空間實現(xiàn)的線程,不是由內(nèi)核管理的線程邑滨,是由用戶態(tài)的線程庫來完成線程的管理日缨;

內(nèi)核線程(Kernel Thread:在內(nèi)核中實現(xiàn)的線程,是由內(nèi)核管理的線程掖看;

輕量級進程(LightWeight Process:在內(nèi)核中來支持用戶線程匣距;

那么,這還需要考慮一個問題哎壳,用戶線程和內(nèi)核線程的對應(yīng)關(guān)系毅待。

首先,第一種關(guān)系是多對一的關(guān)系归榕,也就是多個用戶線程對應(yīng)同一個內(nèi)核線程:


第二種是一對一的關(guān)系尸红,也就是一個用戶線程對應(yīng)一個內(nèi)核線程:


第三種是多對多的關(guān)系,也就是多個用戶線程對應(yīng)到多個內(nèi)核線程:


用戶線程如何理解刹泄?存在什么優(yōu)勢和缺陷外里?

用戶線程是基于用戶態(tài)的線程管理庫來實現(xiàn)的,那么線程控制塊(Thread Control Block, TCB也是在庫里面來實現(xiàn)的特石,對于操作系統(tǒng)而言是看不到這個 TCB 的盅蝗,它只能看到整個進程的 PCB。

所以姆蘸,用戶線程的整個線程管理和調(diào)度风科,操作系統(tǒng)是不直接參與的,而是由用戶級線程庫函數(shù)來完成線程的管理乞旦,包括線程的創(chuàng)建贼穆、終止、同步和調(diào)度等兰粉。

用戶級線程的模型故痊,也就類似前面提到的多對一的關(guān)系,即多個用戶線程對應(yīng)同一個內(nèi)核線程玖姑,如下圖所示:


用戶線程的優(yōu)點

每個進程都需要有它私有的線程控制塊(TCB)列表愕秫,用來跟蹤記錄它各個線程狀態(tài)信息(PC、棧指針焰络、寄存器)戴甩,TCB 由用戶級線程庫函數(shù)來維護,可用于不支持線程技術(shù)的操作系統(tǒng)闪彼;

用戶線程的切換也是由線程庫函數(shù)來完成的甜孤,無需用戶態(tài)與內(nèi)核態(tài)的切換协饲,所以速度特別快;

用戶線程的缺點

由于操作系統(tǒng)不參與線程的調(diào)度缴川,如果一個線程發(fā)起了系統(tǒng)調(diào)用而阻塞茉稠,那進程所包含的用戶線程都不能執(zhí)行了。

當(dāng)一個線程開始運行后把夸,除非它主動地交出 CPU 的使用權(quán)而线,否則它所在的進程當(dāng)中的其他線程無法運行,因為用戶態(tài)的線程沒法打斷當(dāng)前運行中的線程恋日,它沒有這個特權(quán)膀篮,只有操作系統(tǒng)才有,但是用戶線程不是由操作系統(tǒng)管理的岂膳。

由于時間片分配給進程誓竿,故與其他進程比,在多線程執(zhí)行時闷营,每個線程得到的時間片較少,執(zhí)行會比較慢知市;

以上傻盟,就是用戶線程的優(yōu)缺點了。

那內(nèi)核線程如何理解嫂丙?存在什么優(yōu)勢和缺陷娘赴?

內(nèi)核線程是由操作系統(tǒng)管理的,線程對應(yīng)的 TCB 自然是放在操作系統(tǒng)里的跟啤,這樣線程的創(chuàng)建诽表、終止和管理都是由操作系統(tǒng)負(fù)責(zé)。

內(nèi)核線程的模型隅肥,也就類似前面提到的一對一的關(guān)系竿奏,即一個用戶線程對應(yīng)一個內(nèi)核線程,如下圖所示:


內(nèi)核線程的優(yōu)點

在一個進程當(dāng)中腥放,如果某個內(nèi)核線程發(fā)起系統(tǒng)調(diào)用而被阻塞泛啸,并不會影響其他內(nèi)核線程的運行;

分配給線程秃症,多線程的進程獲得更多的 CPU 運行時間候址;

內(nèi)核線程的缺點

在支持內(nèi)核線程的操作系統(tǒng)中,由內(nèi)核來維護進程和線程的上下問信息种柑,如 PCB 和 TCB岗仑;

線程的創(chuàng)建、終止和切換都是通過系統(tǒng)調(diào)用的方式來進行聚请,因此對于系統(tǒng)來說荠雕,系統(tǒng)開銷比較大;

以上,就是內(nèi)核線的優(yōu)缺點了舞虱。

最后的輕量級進程如何理解欢际?

輕量級進程(Light-weight process,LWP)是內(nèi)核支持的用戶線程矾兜,一個進程可有一個或多個 LWP歌焦,每個 LWP 是跟內(nèi)核線程一對一映射的冤灾,也就是 LWP 都是由一個內(nèi)核線程支持。

另外,LWP 只能由內(nèi)核管理并像普通進程一樣被調(diào)度洋魂,Linux 內(nèi)核是支持 LWP 的典型例子。

在大多數(shù)系統(tǒng)中甲棍,LWP與普通進程的區(qū)別也在于它只有一個最小的執(zhí)行上下文和調(diào)度程序所需的統(tǒng)計信息迟螺。一般來說,一個進程代表程序的一個實例荆萤,而 LWP 代表程序的執(zhí)行線程镊靴,因為一個執(zhí)行線程不像進程那樣需要那么多狀態(tài)信息,所以 LWP 也不帶有這樣的信息链韭。

在 LWP 之上也是可以使用用戶線程的偏竟,那么 LWP 與用戶線程的對應(yīng)關(guān)系就有三種:

1 : 1,即一個 LWP 對應(yīng) 一個用戶線程敞峭;

N : 1踊谋,即一個 LWP 對應(yīng)多個用戶線程;

N : N旋讹,即多個 LMP 對應(yīng)多個用戶線程殖蚕;

接下來針對上面這三種對應(yīng)關(guān)系說明它們優(yōu)缺點。先下圖的 LWP 模型:


1 : 1 模式

一個線程對應(yīng)到一個 LWP 再對應(yīng)到一個內(nèi)核線程沉迹,如上圖的進程 4睦疫,屬于此模型。

優(yōu)點:實現(xiàn)并行鞭呕,當(dāng)一個 LWP 阻塞笼痛,不會影響其他 LWP;

缺點:每一個用戶線程琅拌,就產(chǎn)生一個內(nèi)核線程缨伊,創(chuàng)建線程的開銷較大。

N : 1 模式

多個用戶線程對應(yīng)一個 LWP 再對應(yīng)一個內(nèi)核線程进宝,如上圖的進程 2刻坊,線程管理是在用戶空間完成的,此模式中用戶的線程對操作系統(tǒng)不可見党晋。

優(yōu)點:用戶線程要開幾個都沒問題谭胚,且上下文切換發(fā)生用戶空間徐块,切換的效率較高;

缺點:一個用戶線程如果阻塞了灾而,則整個進程都將會阻塞胡控,另外在多核 CPU 中,是沒辦法充分利用 CPU 的旁趟。

M : N 模式

根據(jù)前面的兩個模型混搭一起昼激,就形成M:N模型,該模型提供了兩級控制锡搜,首先多個用戶線程對應(yīng)到多個 LWP橙困,LWP 再一一對應(yīng)到內(nèi)核線程,如上圖的進程 3耕餐。

優(yōu)點:綜合了前兩種優(yōu)點凡傅,大部分的線程上下文發(fā)生在用戶空間,且多個線程又可以充分利用多核 CPU 的資源肠缔。

組合模式

如上圖的進程 5夏跷,此進程結(jié)合1:1模型和M:N模型。開發(fā)人員可以針對不同的應(yīng)用特點調(diào)節(jié)內(nèi)核線程的數(shù)目來達(dá)到物理并行性和邏輯并行性的最佳方案明未。

調(diào)度

進程都希望自己能夠占用 CPU 進行工作槽华,那么這涉及到前面說過的進程上下文切換。

一旦操作系統(tǒng)把進程切換到運行狀態(tài)亚隅,也就意味著該進程占用著 CPU 在執(zhí)行硼莽,但是當(dāng)操作系統(tǒng)把進程切換到其他狀態(tài)時庶溶,那就不能在 CPU 中執(zhí)行了煮纵,于是操作系統(tǒng)會選擇下一個要運行的進程。

選擇一個進程運行這一功能是在操作系統(tǒng)中完成的偏螺,通常稱為調(diào)度程序scheduler)行疏。

那到底什么時候調(diào)度進程,或以什么原則來調(diào)度進程呢套像?

調(diào)度時機

在進程的生命周期中酿联,當(dāng)進程從一個運行狀態(tài)到另外一狀態(tài)變化的時候,其實會觸發(fā)一次調(diào)度夺巩。

比如贞让,以下狀態(tài)的變化都會觸發(fā)操作系統(tǒng)的調(diào)度:

從就緒態(tài) -> 運行態(tài):當(dāng)進程被創(chuàng)建時,會進入到就緒隊列柳譬,操作系統(tǒng)會從就緒隊列選擇一個進程運行喳张;

從運行態(tài) -> 阻塞態(tài):當(dāng)進程發(fā)生 I/O 事件而阻塞時,操作系統(tǒng)必須另外一個進程運行美澳;

從運行態(tài) -> 結(jié)束態(tài):當(dāng)進程退出結(jié)束后销部,操作系統(tǒng)得從就緒隊列選擇另外一個進程運行摸航;

因為,這些狀態(tài)變化的時候舅桩,操作系統(tǒng)需要考慮是否要讓新的進程給 CPU 運行酱虎,或者是否讓當(dāng)前進程從 CPU 上退出來而換另一個進程運行。

另外擂涛,如果硬件時鐘提供某個頻率的周期性中斷读串,那么可以根據(jù)如何處理時鐘中斷 ,把調(diào)度算法分為兩類:

非搶占式調(diào)度算法挑選一個進程歼指,然后讓該進程運行直到被阻塞爹土,或者直到該進程退出,才會調(diào)用另外一個進程踩身,也就是說不會理時鐘中斷這個事情胀茵。

搶占式調(diào)度算法挑選一個進程,然后讓該進程只運行某段時間挟阻,如果在該時段結(jié)束時琼娘,該進程仍然在運行時,則會把它掛起附鸽,接著調(diào)度程序從就緒隊列挑選另外一個進程脱拼。這種搶占式調(diào)度處理,需要在時間間隔的末端發(fā)生時鐘中斷坷备,以便把 CPU 控制返回給調(diào)度程序進行調(diào)度熄浓,也就是常說的時間片機制

調(diào)度原則

原則一:如果運行的程序省撑,發(fā)生了 I/O 事件的請求赌蔑,那 CPU 使用率必然會很低,因為此時進程在阻塞等待硬盤的數(shù)據(jù)返回竟秫。這樣的過程娃惯,勢必會造成 CPU 突然的空閑。所以肥败,為了提高 CPU 利用率趾浅,在這種發(fā)送 I/O 事件致使 CPU 空閑的情況下,調(diào)度程序需要從就緒隊列中選擇一個進程來運行馒稍。

原則二:有的程序執(zhí)行某個任務(wù)花費的時間會比較長皿哨,如果這個程序一直占用著 CPU,會造成系統(tǒng)吞吐量(CPU 在單位時間內(nèi)完成的進程數(shù)量)的降低纽谒。所以证膨,要提高系統(tǒng)的吞吐率,調(diào)度程序要權(quán)衡長任務(wù)和短任務(wù)進程的運行完成數(shù)量佛舱。

原則三:從進程開始到結(jié)束的過程中椎例,實際上是包含兩個時間挨决,分別是進程運行時間和進程等待時間,這兩個時間總和就稱為周轉(zhuǎn)時間订歪。進程的周轉(zhuǎn)時間越小越好脖祈,如果進程的等待時間很長而運行時間很短,那周轉(zhuǎn)時間就很長刷晋,這不是我們所期望的盖高,調(diào)度程序應(yīng)該避免這種情況發(fā)生。

原則四:處于就緒隊列的進程眼虱,也不能等太久喻奥,當(dāng)然希望這個等待的時間越短越好,這樣可以使得進程更快的在 CPU 中執(zhí)行捏悬。所以撞蚕,就緒隊列中進程的等待時間也是調(diào)度程序所需要考慮的原則。

原則五:對于鼠標(biāo)过牙、鍵盤這種交互式比較強的應(yīng)用甥厦,我們當(dāng)然希望它的響應(yīng)時間越快越好,否則就會影響用戶體驗了寇钉。所以刀疙,對于交互式比較強的應(yīng)用,響應(yīng)時間也是調(diào)度程序需要考慮的原則扫倡。

針對上面的五種調(diào)度原則谦秧,總結(jié)成如下:

CPU 利用率:調(diào)度程序應(yīng)確保 CPU 是始終匆忙的狀態(tài),這可提高 CPU 的利用率撵溃;

系統(tǒng)吞吐量:吞吐量表示的是單位時間內(nèi) CPU 完成進程的數(shù)量疚鲤,長作業(yè)的進程會占用較長的 CPU 資源,因此會降低吞吐量征懈,相反石咬,短作業(yè)的進程會提升系統(tǒng)吞吐量揩悄;

周轉(zhuǎn)時間:周轉(zhuǎn)時間是進程運行和阻塞時間總和卖哎,一個進程的周轉(zhuǎn)時間越小越好;

等待時間:這個等待時間不是阻塞狀態(tài)的時間删性,而是進程處于就緒隊列的時間亏娜,等待的時間越長,用戶越不滿意蹬挺;

響應(yīng)時間:用戶提交請求到系統(tǒng)第一次產(chǎn)生響應(yīng)所花費的時間维贺,在交互式系統(tǒng)中,響應(yīng)時間是衡量調(diào)度算法好壞的主要標(biāo)準(zhǔn)巴帮。

說白了溯泣,這么多調(diào)度原則虐秋,目的就是要使得進程要「快」。

調(diào)度算法

不同的調(diào)度算法適用的場景也是不同的垃沦。

接下來客给,說說在單核 CPU 系統(tǒng)中常見的調(diào)度算法。

01 先來先服務(wù)調(diào)度算法

最簡單的一個調(diào)度算法肢簿,就是非搶占式的先來先服務(wù)(First Come First Severd, FCFS)算法


顧名思義靶剑,先來后到,每次從就緒隊列選擇最先進入隊列的進程池充,然后一直運行桩引,直到進程退出或被阻塞,才會繼續(xù)從隊列中選擇第一個進程接著運行收夸。

這似乎很公平坑匠,但是當(dāng)一個長作業(yè)先運行了,那么后面的短作業(yè)等待的時間就會很長卧惜,不利于短作業(yè)笛辟。

FCFS 對長作業(yè)有利,適用于 CPU 繁忙型作業(yè)的系統(tǒng)序苏,而不適用于 I/O 繁忙型作業(yè)的系統(tǒng)手幢。

02 最短作業(yè)優(yōu)先調(diào)度算法

最短作業(yè)優(yōu)先(Shortest Job First, SJF)調(diào)度算法同樣也是顧名思義,它會優(yōu)先選擇運行時間最短的進程來運行忱详,這有助于提高系統(tǒng)的吞吐量围来。


這顯然對長作業(yè)不利,很容易造成一種極端現(xiàn)象匈睁。

比如监透,一個長作業(yè)在就緒隊列等待運行,而這個就緒隊列有非常多的短作業(yè)航唆,那么就會使得長作業(yè)不斷的往后推胀蛮,周轉(zhuǎn)時間變長,致使長作業(yè)長期不會被運行糯钙。

03 高響應(yīng)比優(yōu)先調(diào)度算法

前面的「先來先服務(wù)調(diào)度算法」和「最短作業(yè)優(yōu)先調(diào)度算法」都沒有很好的權(quán)衡短作業(yè)和長作業(yè)粪狼。

那么,高響應(yīng)比優(yōu)先 (Highest Response Ratio Next, HRRN)調(diào)度算法主要是權(quán)衡了短作業(yè)和長作業(yè)任岸。

每次進行進程調(diào)度時再榄,先計算「響應(yīng)比優(yōu)先級」,然后把「響應(yīng)比優(yōu)先級」最高的進程投入運行享潜,「響應(yīng)比優(yōu)先級」的計算公式:


從上面的公式困鸥,可以發(fā)現(xiàn):

如果兩個進程的「等待時間」相同時,「要求的服務(wù)時間」越短剑按,「響應(yīng)比」就越高疾就,這樣短作業(yè)的進程容易被選中運行澜术;

如果兩個進程「要求的服務(wù)時間」相同時,「等待時間」越長猬腰,「響應(yīng)比」就越高瘪板,這就兼顧到了長作業(yè)進程,因為進程的響應(yīng)比可以隨時間等待的增加而提高漆诽,當(dāng)其等待時間足夠長時侮攀,其響應(yīng)比便可以升到很高,從而獲得運行的機會厢拭;

04 時間片輪轉(zhuǎn)調(diào)度算法

最古老兰英、最簡單、最公平且使用最廣的算法就是時間片輪轉(zhuǎn)(Round Robin, RR)調(diào)度算法供鸠。


每個進程被分配一個時間段畦贸,稱為時間片(Quantum),即允許該進程在該時間段中運行楞捂。

如果時間片用完薄坏,進程還在運行,那么將會把此進程從 CPU 釋放出來寨闹,并把 CPU 分配另外一個進程胶坠;

如果該進程在時間片結(jié)束前阻塞或結(jié)束,則 CPU 立即進行切換繁堡;

另外沈善,時間片的長度就是一個很關(guān)鍵的點:

如果時間片設(shè)得太短會導(dǎo)致過多的進程上下文切換,降低了 CPU 效率椭蹄;

如果設(shè)得太長又可能引起對短作業(yè)進程的響應(yīng)時間變長闻牡。將

通常時間片設(shè)為20ms~50ms通常是一個比較合理的折中值。

05 最高優(yōu)先級調(diào)度算法

前面的「時間片輪轉(zhuǎn)算法」做了個假設(shè)绳矩,即讓所有的進程同等重要罩润,也不偏袒誰,大家的運行時間都一樣翼馆。

但是割以,對于多用戶計算機系統(tǒng)就有不同的看法了,它們希望調(diào)度是有優(yōu)先級的写妥,即希望調(diào)度程序能從就緒隊列中選擇最高優(yōu)先級的進程進行運行拳球,這稱為最高優(yōu)先級(Highest Priority First审姓,HPF)調(diào)度算法珍特。

進程的優(yōu)先級可以分為,靜態(tài)優(yōu)先級或動態(tài)優(yōu)先級:

靜態(tài)優(yōu)先級:創(chuàng)建進程時候魔吐,就已經(jīng)確定了優(yōu)先級了扎筒,然后整個運行時間優(yōu)先級都不會變化莱找;

動態(tài)優(yōu)先級:根據(jù)進程的動態(tài)變化調(diào)整優(yōu)先級,比如如果進程運行時間增加嗜桌,則降低其優(yōu)先級奥溺,如果進程等待時間(就緒隊列的等待時間)增加,則升高其優(yōu)先級骨宠,也就是隨著時間的推移增加等待進程的優(yōu)先級浮定。

該算法也有兩種處理優(yōu)先級高的方法,非搶占式和搶占式:

非搶占式:當(dāng)就緒隊列中出現(xiàn)優(yōu)先級高的進程层亿,運行完當(dāng)前進程桦卒,再選擇優(yōu)先級高的進程。

搶占式:當(dāng)就緒隊列中出現(xiàn)優(yōu)先級高的進程匿又,當(dāng)前進程掛起方灾,調(diào)度優(yōu)先級高的進程運行。

但是依然有缺點碌更,可能會導(dǎo)致低優(yōu)先級的進程永遠(yuǎn)不會運行裕偿。

06 多級反饋隊列調(diào)度算法

多級反饋隊列(Multilevel Feedback Queue)調(diào)度算法是「時間片輪轉(zhuǎn)算法」和「最高優(yōu)先級算法」的綜合和發(fā)展。

顧名思義:

「多級」表示有多個隊列痛单,每個隊列優(yōu)先級從高到低嘿棘,同時優(yōu)先級越高時間片越短。

「反饋」表示如果有新的進程加入優(yōu)先級高的隊列時旭绒,立刻停止當(dāng)前正在運行的進程蔫巩,轉(zhuǎn)而去運行優(yōu)先級高的隊列;


來看看快压,它是如何工作的:

設(shè)置了多個隊列圆仔,賦予每個隊列不同的優(yōu)先級,每個隊列優(yōu)先級從高到低蔫劣,同時優(yōu)先級越高時間片越短坪郭;

新的進程會被放入到第一級隊列的末尾,按先來先服務(wù)的原則排隊等待被調(diào)度脉幢,如果在第一級隊列規(guī)定的時間片沒運行完成歪沃,則將其轉(zhuǎn)入到第二級隊列的末尾,以此類推嫌松,直至完成沪曙;

當(dāng)較高優(yōu)先級的隊列為空,才調(diào)度較低優(yōu)先級的隊列中的進程運行萎羔。如果進程運行時液走,有新進程進入較高優(yōu)先級的隊列,則停止當(dāng)前運行的進程并將其移入到原隊列末尾,接著讓較高優(yōu)先級的進程運行缘眶;

可以發(fā)現(xiàn)嘱根,對于短作業(yè)可能可以在第一級隊列很快被處理完。對于長作業(yè)巷懈,如果在第一級隊列處理不完该抒,可以移入下次隊列等待被執(zhí)行,雖然等待的時間變長了顶燕,但是運行時間也會更長了凑保,所以該算法很好的兼顧了長短作業(yè),同時有較好的響應(yīng)時間涌攻。

看的迷迷糊糊愉适?那我拿去銀行辦業(yè)務(wù)的例子,把上面的調(diào)度算法串起來癣漆,你還不懂维咸,你錘我!

辦理業(yè)務(wù)的客戶相當(dāng)于進程惠爽,銀行窗口工作人員相當(dāng)于 CPU癌蓖。

現(xiàn)在,假設(shè)這個銀行只有一個窗口(單核 CPU )婚肆,那么工作人員一次只能處理一個業(yè)務(wù)租副。


那么最簡單的處理方式,就是先來的先處理较性,后面來的就乖乖排隊用僧,這就是先來先服務(wù)(FCFS)調(diào)度算法。但是萬一先來的這位老哥是來貸款的赞咙,這一談就好幾個小時责循,一直占用著窗口,這樣后面的人只能干等攀操,或許后面的人只是想簡單的取個錢院仿,幾分鐘就能搞定,卻因為前面老哥辦長業(yè)務(wù)而要等幾個小時速和,你說氣不氣人歹垫?


有客戶抱怨了,那我們就要改進颠放,我們干脆優(yōu)先給那些幾分鐘就能搞定的人辦理業(yè)務(wù)排惨,這就是短作業(yè)優(yōu)先(SJF)調(diào)度算法。聽起來不錯碰凶,但是依然還是有個極端情況暮芭,萬一辦理短業(yè)務(wù)的人非常的多鹿驼,這會導(dǎo)致長業(yè)務(wù)的人一直得不到服務(wù),萬一這個長業(yè)務(wù)是個大客戶谴麦,那不就撿了芝麻丟了西瓜


那就公平起見蠢沿,現(xiàn)在窗口工作人員規(guī)定伸头,每個人我只處理 10 分鐘匾效。如果 10 分鐘之內(nèi)處理完,就馬上換下一個人恤磷。如果沒處理完面哼,依然換下一個人,但是客戶自己得記住辦理到哪個步驟了扫步。這個也就是時間片輪轉(zhuǎn)(RR)調(diào)度算法魔策。但是如果時間片設(shè)置過短,那么就會造成大量的上下文切換河胎,增大了系統(tǒng)開銷闯袒。如果時間片過長,相當(dāng)于退化成退化成 FCFS 算法了游岳。


既然公平也可能存在問題政敢,那銀行就對客戶分等級,分為普通客戶胚迫、VIP 客戶喷户、SVIP 客戶。只要高優(yōu)先級的客戶一來访锻,就第一時間處理這個客戶褪尝,這就是最高優(yōu)先級(HPF)調(diào)度算法。但依然也會有極端的問題期犬,萬一當(dāng)天來的全是高級客戶河哑,那普通客戶不是沒有被服務(wù)的機會,不把普通客戶當(dāng)人是嗎龟虎?那我們把優(yōu)先級改成動態(tài)的灾馒,如果客戶辦理業(yè)務(wù)時間增加,則降低其優(yōu)先級遣总,如果客戶等待時間增加睬罗,則升高其優(yōu)先級。


那有沒有兼顧到公平和效率的方式呢旭斥?這里介紹一種算法容达,考慮的還算充分的,多級反饋隊列(MFQ)調(diào)度算法垂券,它是時間片輪轉(zhuǎn)算法和優(yōu)先級算法的綜合和發(fā)展花盐。它的工作方式:


銀行設(shè)置了多個排隊(就緒)隊列羡滑,每個隊列都有不同的優(yōu)先級,各個隊列優(yōu)先級從高到低算芯,同時每個隊列執(zhí)行時間片的長度也不同柒昏,優(yōu)先級越高的時間片越短

新客戶(進程)來了熙揍,先進入第一級隊列的末尾职祷,按先來先服務(wù)原則排隊等待被叫號(運行)。如果時間片用完客戶的業(yè)務(wù)還沒辦理完成届囚,則讓客戶進入到下一級隊列的末尾有梆,以此類推,直至客戶業(yè)務(wù)辦理完成意系。

當(dāng)?shù)谝患夑犃袥]人排隊時泥耀,就會叫號二級隊列的客戶。如果客戶辦理業(yè)務(wù)過程中蛔添,有新的客戶加入到較高優(yōu)先級的隊列痰催,那么此時辦理中的客戶需要停止辦理,回到原隊列的末尾等待再次叫號迎瞧,因為要把窗口讓給剛進入較高優(yōu)先級隊列的客戶夸溶。

可以發(fā)現(xiàn),對于要辦理短業(yè)務(wù)的客戶來說夹攒,可以很快的輪到并解決蜘醋。對于要辦理長業(yè)務(wù)的客戶,一下子解決不了咏尝,就可以放到下一個隊列压语,雖然等待的時間稍微變長了,但是輪到自己的辦理時間也變長了编检,也可以接受胎食,不會造成極端的現(xiàn)象,可以說是綜合上面幾種算法的優(yōu)點允懂。

作者:小林coding

鏈接:https://www.zhihu.com/question/44087187/answer/2062919643

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厕怜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蕾总,更是在濱河造成了極大的恐慌粥航,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件生百,死亡現(xiàn)場離奇詭異递雀,居然都是意外死亡,警方通過查閱死者的電腦和手機蚀浆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門缀程,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搜吧,“玉大人,你說我怎么就攤上這事杨凑÷四危” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵撩满,是天一觀的道長蜒程。 經(jīng)常有香客問我,道長鹦牛,這世上最難降的妖魔是什么搞糕? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任勇吊,我火速辦了婚禮曼追,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘汉规。我一直安慰自己礼殊,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布针史。 她就那樣靜靜地躺著晶伦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啄枕。 梳的紋絲不亂的頭發(fā)上婚陪,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音频祝,去河邊找鬼泌参。 笑死,一個胖子當(dāng)著我的面吹牛常空,可吹牛的內(nèi)容都是我干的沽一。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼漓糙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起被因,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤择卦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后醉鳖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捡硅,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年辐棒,在試婚紗的時候發(fā)現(xiàn)自己被綠了病曾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牍蜂。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖泰涂,靈堂內(nèi)的尸體忽然破棺而出鲫竞,到底是詐尸還是另有隱情,我是刑警寧澤逼蒙,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布从绘,位于F島的核電站,受9級特大地震影響是牢,放射性物質(zhì)發(fā)生泄漏僵井。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一驳棱、第九天 我趴在偏房一處隱蔽的房頂上張望批什。 院中可真熱鬧,春花似錦社搅、人聲如沸驻债。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽合呐。三九已至,卻和暖如春笙以,著一層夾襖步出監(jiān)牢的瞬間淌实,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工猖腕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拆祈,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓谈息,卻偏偏與公主長得像缘屹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子侠仇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容