用「閃電俠」的例子解釋一下進程和線程

語言: CN / TW / HK

1.

艾倫在一次粒子加速器爆炸大事故中獲得了極速移動的超能力,因此開始化身為超級英雄“閃電俠”。類比之下,CPU是計算機最核心的部件,它負責指令的讀取和執行,每秒可以執行幾十億條指令!其實比閃電俠還要快得多。

I Am the Flash

小閃這種能力很快就被FBI發現了,為了好好利用小閃,FBI僱傭了小閃為其特別行動小組A執行任務。

説是特別行動小組,其實除了小閃之外只有一個A博士,小閃日常的工作就是取得A博士的指令並且執行。這就是計算機早期的單進程模型。

2.

特別行動小組,禁止入內

但是A博士從蒐集情報到得出正確的指令畢竟需要時間,而小閃執行指令的速度又太快,所以在FBI高層眼裏,A博士總是忙忙碌碌,而小閃成天優哉遊哉。

為了提高小閃的利用率,FBI在特別行動小組辦公室的樓下,着手成立另一個特別行動小組B。

這個着手成立的過程就是編碼,而編碼的結果就是得到一個能夠完成某個特定功能的程序。

很快,特別行動小組B在B博士的獨自掌管下開始暗中運行。這就是進程的誕生,進程其實就是運行的程序。現在FBI特別行動小組進入了多進程時代。

3.

雖然都是FBI的特別行動小組,若無特殊情況,A和B通常井水不犯河水,他們都認為自己壟斷了FBI的所有資源,但這其實只是FBI的小把戲而已。

背後的含義就是每個進程採用了完全相同的虛擬地址空間,然而經由操作系統和硬件MMU協作,映射到不同的物理地址空間。

不同的進程,都有各自獨立的物理內存空間,特別行動小組A和B之間的通信就是進程間通信(IPC)。

4.

小閃雖然速度快,但是依然沒辦法在同一時刻同時執行A博士和B博士兩個人的指令,就好像人不能在向右看的同時向左看。

A博士和B博士常常為此大打出手,誰都想佔用小閃更多的時間,好完成自己的KPI。

FBI領導層想了一個辦法,新成立了一個調度小組,用來給各個小組分配小閃的使用時間。一開始,調度小組會給每個進程分配相等的一小段時間,然後每個小組輪番地佔用小閃執行相應時間的任務。這就是CPU的時間片分配。

如果小閃在這一小段時間內還沒執行完,那也必須得停,但是得保存一下執行進度,下次繼續從結束的地方開始做。這就是CPU的上下文切換。

這樣一來,A博士和B博士的KPI完成了,小閃也忙起來了。説是忙起來,但是花在指令執行上的時間其實也沒多多少,基本就是在兩個小組之間反覆橫跳了,小閃的工作依然愜意。

5.

兩個博士眼紅於小閃依然有大把的空閒時間,居然頗有默契地發起了招聘公告,廣攬天下英才,勢必要多找點事情給小閃做。

FBI的英雄帖

很快,行動小組內的成員越來越多,並且每個成員的任務都不一樣,比如有些人負責查閲資料,有些人負責收取訊息......小組內各個成員分工協作,完成特別小組的共同目標。自此進入多線程時代。

線程就好比是小組內的成員,一個進程可以包含很多個線程。

進程是資源分配的基本單位,比如FBI給特別小組分配辦公場所。

線程是CPU調度的基本單位,比如小閃需要執行每個小組成員的指令。

6.

成員多了,管理就成了一個新的問題。如果每個成員只是自説自話,完全不講究團隊協作,極容易造成團隊內部衝突。

為此,FBI制定了幾個策略。對應的是線程的同步。

7.

給廁所鎖死

行動小組內的資源不同,共享的程度也不一樣。比如廁所,當有人正在使用的時候,其他人只能等待,如果貿然闖進去必然出現衝突。這表示進程中的某些共享內存同一時間只能由一個線程使用,其他線程必須等待該線程結束使用之後才能繼續使用。

一個防止其他人進入的簡單方法就是給廁所添加一把鎖,首先佔用廁所的人上鎖,其他人看到有鎖之後就在門口排隊,直到佔用的線程釋放鎖才能進入。這個策略叫做「互斥鎖」,英文叫做Mutex

8.

進入會議室之前先領個小可愛

不同於廁所,會議室就能同時允許10個人進入,如果人數超過10個,多出來的人只能排隊等着,除非有人空出位置,其他人才能進入會議室。

為了解決這個問題,FBI在會議室的門口掛了10把鑰匙,每個人進入會議室前都要取一把鑰匙,出來時把鑰匙放回原位。如果後來者發現沒有鑰匙了,就在會議室門口等待。這種策略叫做「信號量」,互斥鎖只允許一個線程進入臨界區,信號量允許多個線程同時進入臨界區。

9.

兔子不是在睡覺,只是在等待被喚醒

有些時候,行動小組的某些任務比較複雜,需要流水線式作業。上游的人員做完之後把結果交付給下游人員處理,這就是典型的生產者消費者模式。

如果生產者生產得太快,我們可以適當讓上游的人員停止作業,等待某個時機喚醒生產者;反之,如果消費者消費得太快,我們可以適當讓下游的人員停止作業,等到某個時機喚醒消費者。

這種策略叫做「條件變量」,背後的原理是當線程在等待某些條件時使線程進入睡眠狀態,一旦條件滿足,就喚醒。

10.

頻繁升級的放映機

最後拿行動小組的放映機舉個例子。很多成員喜歡在休息時間坐在一起使用放映機看個電影,消遣一下時間,類似於多線程對同一資源進行讀操作,這種情況下不管多少人在看電影都不會出現問題。

但是偏偏有人在其他人看電影的時候要升級一下放映機的操作系統,這肯定會影響其他人的觀影體驗;反之,在升級操作系統的時候,有人要看電影,這同樣會對升級人員造成困擾。

這種時候我們可以定一個策略,當觀影時,隨時歡迎其他觀影人員使用觀看;當升級時,禁止任何觀影人員和任何其他升級人員使用。

這種方式稱為「讀寫鎖」,也叫做「共享-獨佔鎖」,“觀影”對應的就是線程的讀操作,“升級”對應的就是線程的寫操作。具體來説一般有兩種情況:

  1. 讀寫鎖處於寫鎖定的狀態,則在解鎖之前,所有試圖加鎖的線程都會阻塞;
  2. 讀寫鎖處於讀鎖定的狀態,則所有試圖以讀模式加鎖的線程都可得到訪問權,但是以寫模式加鎖的線程則會阻塞;

公眾號「蟬沐風」,歡迎關注,邂逅更多精彩文章!

完!