1. 程式人生 > >面試官:多執行緒一定比單執行緒跑得快嗎?

面試官:多執行緒一定比單執行緒跑得快嗎?

Part 1 思考人生的多執行緒

我們一直在說高併發、多執行緒、分散式應用,但是高併發情況下,多執行緒一定就快嗎?

我們首先要理解下併發執行是怎麼一回事。

為什麼一般意義上來說多執行緒就能抵抗高併發,執行速度就能得到提升?

所謂併發執行就是某個時間段CPU能執行多個任務。

例如早上起來後,刷牙、照鏡子、思考這復讀機一般的人生是為哪般?

但是我們真的能同時做這麼多事嗎?

不是的,其實是在大腦下達指令後,刷牙、照鏡子這種動作已經形成了肌肉記憶、固定動作,然後我們又有了幾分鐘思考人生的時光了。

同樣的道理放在計算上也是一樣。

我們首先要明白一個基礎知識,計算機的主要元件為CPU、記憶體、磁碟;而在這三大元件中,CPU的執行速率高於記憶體1000倍以上,記憶體的執行速率高於磁碟1000倍以上。

當然,這只是我的口嗨,並不是真的1000倍。

你只要知道他們的執行速率對比,CPU > 記憶體 > 磁碟就好了,並且要快很多。

Part 2 應付多個嬰兒的哺乳媽媽

2.1 上下文切換

多執行緒執行就像是很多個嬰兒跟媽媽要奶喝一樣,怎麼辦?媽媽就兩個哺乳器官啊?最多就同時處理兩個嬰兒同時肚子餓的任務。

這已經是雙核CPU了。實際上,媽媽只能同時處理一個嬰兒哺乳的任務而已,沒辦法同時把兩個孩子抱在懷裡。你以為是母豬可以同時喂很多小豬呢?

所以只好讓嬰兒先喝點,抵抵飽,哄一鬨,然後換另外的孩子。

這就是CPU的【上下文切換】。

2.2 執行緒爭用

而很多時候,我們需要執行的任務並不是一樣的。

還是以嬰兒為例,嬰兒們同時大哭,要求佔用媽媽的時間,ABC嬰兒要換尿布、DEF嬰兒要喝奶。

怎麼辦?頭大。

這就是【執行緒爭用】。

2.3 併發執行

媽媽要開始安撫孩子了,但是隻能一個個來啊,要麼先找幾個奶瓶衝奶讓要喝奶的自己抱奶瓶喝奶,再去處理換尿布。

要麼先去處理尿布,再去衝奶。

衝奶這個動作很快,但是喝奶的時間很長。媽媽考慮了下,決定先衝奶,然後讓他們自己抱奶瓶。

這就是【併發執行】。

2.4 自旋鎖

但是衝奶的時候,嬰兒還在哭,等待著媽媽送來奶瓶和換尿布怎麼辦?

這就是【自旋鎖】。如果CPU一直不處理任務,就迴圈等待,直到CPU來處理。

2.5 互斥鎖

如果媽媽衝奶時,抱了一個嬰兒在懷裡哄著不哭,其他的嬰兒們沒指望了,就不哭了(當然,實際上不可能),等著媽媽空出手來又繼續哭,競爭媽媽的懷抱(笑)。

這就叫【互斥鎖】。它跟自旋鎖類似,不同的是競爭不到鎖的執行緒會回去睡會覺,等到鎖可用再來競爭。競爭失敗者繼續回去睡覺直到再次接到通知。

2.6 樂觀鎖

如果DEF拿到了奶瓶就不哭了,直到一瓶奶喝完還是喝不飽,才開始哭,要媽媽。這叫【樂觀鎖】。

樂觀鎖在資料庫的資料操作中,就是提交更新那一刻,才給相關資料行加鎖。

2.7 悲觀鎖

如果DEF拿到了奶瓶還是哭,因為他們還需要媽媽抱著喝才行。這叫【悲觀鎖】。

悲觀鎖就是如果一個事務操作用了鎖,那只有當這個事務把鎖釋放(把媽媽給釋放),其他事務才能夠執行與該鎖衝突的操作。

2.8 時間片分配演算法

我們觀察以上的故事,可以發現它們並不是同時執行的。

而CPU相比媽媽來說,它的執行速度就更快了,它通過給每個執行緒分配CPU時間來實現任務執行,這個時間片一般是幾十毫秒。

這樣不停地來回切換任務,執行程式,劃分時間片,就叫做【時間片分配演算法】。

2.9 執行緒與程序

上面說的是一個哺育室的故事,以JAVA而言,這就是一個【程序】。

如果媽媽還管著另一個哺育室,就又是一個程序。

一個哺育室有很多嬰兒,嬰兒們也可以認為是一個個執行緒。

所以【一個程序可以包含多個執行緒】。

而嬰兒們又享受著哺育室的公共環境與玩具。這就是【記憶體環境共享】。

在Java應用中,每個執行緒都是執行在程序的上下文中,共享【同樣的程式碼和全域性資料】。

如果其中一個哺育室的裝修風格、哺育規則變了,也不會影響到另一個哺育室。

所以在多程序環境中,任何一個程序的終止,都不會影響到其他程序。

所以在單核CPU時代,我們在一臺電腦上也可以同時聽歌、寫作,可以一邊看電影、一邊論壇灌水【多程序】,而一個論壇裡又可以有多個使用者同時灌水【多執行緒】。

part 3 多執行緒一定比單執行緒跑得快嗎?

回到最初的話題。

面試官:

如果有很多工,每個任務需要CPU處理的時間都很長,佔用的時間片很高,那麼,多執行緒還能快嗎?

如果任務很少的情況下又是怎麼樣呢?

例如只有兩個嬰兒,來回換著哺乳快還是一個個餵飽來得快呢?

什麼情況下適合使用多執行緒呢?

除了CPU、記憶體、磁碟,還有什麼能影響併發執行的速度呢?

 

如果你是面試者,怎麼回答呢?留言給我說說看你的看法。

如果你對我上面的解釋並不滿意,有著不同的看法,也歡迎來噴一噴。

--------------------------------------------------------
歡迎關注我的公眾號:姚毛毛的部落格

這裡有我的程式設計生涯感悟與總結,有Java、Linux、Oracle、mysql的相關技術,有工作中進行的架構設計實踐和讀書理論,有JVM、Linux、資料庫的效能調優,有……

有技術,有情懷,有溫度

歡迎關注我:姚毛毛& 妖生