Part 1 思考人生的多線程

          我們一直在說高并發(fā)、多線程、分布式應用,但是高并發(fā)情況下,多線程一定就快嗎?

          我們首先要理解下并發(fā)運行是怎么一回事。

          為什么一般意義上來說多線程就能抵抗高并發(fā),運行速度就能得到提升?

          所謂并發(fā)運行就是某個時間段CPU能執(zhí)行多個任務。

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

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

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

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


          我們首先要明白一個基礎知識,計算機的主要組件為CPU、內(nèi)存、磁盤;而在這三大組件中,CPU的運行速率高于內(nèi)存1000倍以上,內(nèi)存的運行速率高于磁盤1000倍以上。

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

          你只要知道他們的運行速率對比,CPU > 內(nèi)存 > 磁盤就好了,并且要快很多。

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

          2.1 上下文切換

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

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

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

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

          2.2 線程爭用

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

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

          怎么辦?頭大。

          這就是【線程爭用】。

          2.3 并發(fā)執(zhí)行

          媽媽要開始安撫孩子了,但是只能一個個來啊,要么先找?guī)讉€奶瓶沖奶讓要喝奶的自己抱奶瓶喝奶,再去處理換尿布。

          要么先去處理尿布,再去沖奶。

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

          這就是【并發(fā)執(zhí)行】。

          2.4 自旋鎖

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

          這就是【自旋鎖】。如果CPU一直不處理任務,就循環(huán)等待,直到CPU來處理。

          2.5 互斥鎖

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

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

          2.6 樂觀鎖

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

          樂觀鎖在數(shù)據(jù)庫的數(shù)據(jù)操作中,就是提交更新那一刻,才給相關數(shù)據(jù)行加鎖。

          2.7 悲觀鎖

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

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

          2.8 時間片分配算法

          我們觀察以上的故事,可以發(fā)現(xiàn)它們并不是同時運行的。

          而CPU相比媽媽來說,它的執(zhí)行速度就更快了,它通過給每個線程分配CPU時間來實現(xiàn)任務運行,這個時間片一般是幾十毫秒。

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

          2.9 線程與進程

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

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

          一個哺育室有很多嬰兒,嬰兒們也可以認為是一個個線程。

          所以【一個進程可以包含多個線程】。

          而嬰兒們又享受著哺育室的公共環(huán)境與玩具。這就是【內(nèi)存環(huán)境共享】。

          在Java應用中,每個線程都是運行在進程的上下文中,共享【同樣的代碼和全局數(shù)據(jù)】。

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

          所以在多進程環(huán)境中,任何一個進程的終止,都不會影響到其他進程。

          所以在單核CPU時代,我們在一臺電腦上也可以同時聽歌、寫作,可以一邊看電影、一邊論壇灌水【多進程】,而一個論壇里又可以有多個用戶同時灌水【多線程】。

          part 3 多線程一定比單線程跑得快嗎?

          回到最初的話題。

          面試官:

          如果有很多任務,每個任務需要CPU處理的時間都很長,占用的時間片很高,那么,多線程還能快嗎?

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

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

          什么情況下適合使用多線程呢?

          除了CPU、內(nèi)存、磁盤,還有什么能影響并發(fā)執(zhí)行的速度呢?

          ?

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

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

          --------------------------------------------------------
          歡迎關注我的公眾號:姚毛毛的博客


          這里有我的編程生涯感悟與總結(jié),有Java、Linux、Oracle、mysql的相關技術,有工作中進行的架構設計實踐和讀書理論,有JVM、Linux、數(shù)據(jù)庫的性能調(diào)優(yōu),有……

          有技術,有情懷,有溫度

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


          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點信息
          問題反饋
          郵箱:[email protected]
          QQ群:637538335
          關注微信

                一级特黄60分钟免费看软件下载 | 久久亚洲AV午夜福利精品一区 | 与美女做爱的网站 | 噜噜噜噜影院 | 久久精品操 |