上次談到了什么是線程配阵,那么秉持存在既有價(jià)值的原則,我們探討一下為什么需要線程救拉,再附帶一些關(guān)鍵性的小問題瘫拣。
在早期時(shí)候麸拄,計(jì)算機(jī)能力比較弱拢切,強(qiáng)調(diào)功能性而非易用性,直白點(diǎn)五慈,就是只要能干成泻拦,總比我干的快忽媒,其他都無所謂猾浦。但是隨著時(shí)代發(fā)展,對(duì)計(jì)算機(jī)的依賴越來越多音瓷,那么要求也越來越多绳慎。如果你現(xiàn)在電腦動(dòng)不動(dòng)就卡杏愤,鼠標(biāo)轉(zhuǎn)圈圈,你估計(jì)就受不了了通殃,更嚴(yán)重的画舌,動(dòng)不動(dòng)電腦就要自動(dòng)重啟曲聂,估計(jì)你要砸電腦了佑惠。但是剛開始,計(jì)算機(jī)的確是會(huì)經(jīng)常自動(dòng)重啟的旭咽,因?yàn)橛?jì)算機(jī)那個(gè)時(shí)候不分用戶和操作系統(tǒng)轻专,落到底層就是察蹲,計(jì)算機(jī)所需要的資源洽议,跟應(yīng)用程度所需要的資源是放在一起的亚兄。上一節(jié)也說過這個(gè)情況审胚。這是不安全的膳叨,如果應(yīng)用程序有問題痘系,會(huì)導(dǎo)致整個(gè)操作系統(tǒng)受牽連。
你可以認(rèn)為為了解決這個(gè)問題昭雌,首先讓操作系統(tǒng)使用的空間跟用戶應(yīng)用程度使用的空間分來了(內(nèi)核態(tài)和用戶態(tài))烛卧,然后為了讓用戶應(yīng)用之間也不互相影響总放,大家也都各自在各自的地址空間里面吧间聊。這樣實(shí)現(xiàn)了隔離哎榴,解決了相互牽連的問題僵蛛。
后來飘言,人們發(fā)現(xiàn)驼侠,應(yīng)用程序在執(zhí)行的時(shí)候倒源,經(jīng)常會(huì)遇到一些執(zhí)行時(shí)間比較長(zhǎng)的操作,這樣的話热某,會(huì)導(dǎo)致整個(gè)應(yīng)用程序因?yàn)榈却荒茼憫?yīng)用戶的請(qǐng)求昔馋,這樣用戶就會(huì)想秘遏,這應(yīng)用有問題垄提。在執(zhí)行長(zhǎng)時(shí)間任務(wù)铡俐,比如請(qǐng)求一個(gè)遠(yuǎn)程文件凰兑,這個(gè)時(shí)候,除了干等著之外审丘,還可以去干點(diǎn)別的吏够。那怎么干呢?
上一節(jié)我們說到線程其實(shí)就是一組任務(wù)執(zhí)行序列的組合滩报,既然這樣锅知,如果我們把一組任務(wù)序列給變成兩組,讓長(zhǎng)時(shí)間執(zhí)行的一組脓钾,短時(shí)間執(zhí)行的一組售睹,再加上CPU可以按照時(shí)間片切換執(zhí)行序列,這不就可以穿插執(zhí)行兩組任務(wù)了嗎可训?那么對(duì)用戶體驗(yàn)而言昌妹,就不需要一直等長(zhǎng)時(shí)間執(zhí)行的任務(wù),點(diǎn)擊鼠標(biāo)或者按鈕就可以得到相應(yīng)了握截,因?yàn)镃PU時(shí)間片很短。
好了牢裳,以前的時(shí)候恬汁,應(yīng)用程序分配的地址空間里面只有一個(gè)執(zhí)行序列约巷,現(xiàn)在有兩個(gè)了踩麦,這需要區(qū)分一下反粥。那這個(gè)地址空間就叫做進(jìn)程吧尤蒿,里面的執(zhí)行序列就叫做線程吧巩螃。讀者不要誤會(huì),這個(gè)不是段子,進(jìn)程的概念和線程應(yīng)該是同時(shí)出現(xiàn)的,因?yàn)闆]有線程,就不需要區(qū)分進(jìn)程慰技,直接叫地址空間就可以了糟红。地址空間里面本身就有一個(gè)執(zhí)行序列柒爸,否則應(yīng)用程序就沒有存在的意義了阳藻。所以蛔外,進(jìn)程里面至少有一個(gè)線程矛纹,但是一個(gè)線程肄方,就沒必要單獨(dú)區(qū)分了逝薪。
那為什么需要更多的線程呢尼啡,就是為了讓用戶體驗(yàn)更好书聚。這個(gè)我們就不多說了驯杜,先問一個(gè)問題糯景,多線程就一定快嗎略贮?
我們來說下串行拄丰、并行卓箫、并發(fā)的概念烹卒,然后再來回答這個(gè)問題炎码。
嚴(yán)格意義上講潦闲,并行和串行和一組概念和敬,并發(fā)跟它們不是一個(gè)范疇的概念舱痘。串行是指频丘,在一個(gè)時(shí)間點(diǎn)员萍,只可能有一個(gè)任務(wù)序列正在被執(zhí)行腾降;并行則是在一個(gè)時(shí)間點(diǎn),有至少兩個(gè)任務(wù)序列正在被執(zhí)行碎绎。其實(shí)螃壤,并行跟串行嚴(yán)格上講,跟多不多線程沒關(guān)系筋帖,它們只跟CPU的個(gè)數(shù)有關(guān)系奸晴,只要CPU核數(shù)只有一個(gè),再多的線程也是站好成一隊(duì)日麸,一個(gè)一個(gè)執(zhí)行寄啼;CPU核數(shù)大于1個(gè)的時(shí)候,那么線程的執(zhí)行序列就可以拍成至少2對(duì)代箭,那么就同一時(shí)刻墩划,就有多于一個(gè)的線程正在被執(zhí)行,這才是并行嗡综。
那來說并發(fā)乙帮,并發(fā)說的是一個(gè)時(shí)間段內(nèi),而非一個(gè)時(shí)刻蛤高。一個(gè)時(shí)間段內(nèi)蚣旱,有多個(gè)任務(wù)交替進(jìn)行,是為并發(fā)戴陡∪蹋可以理解為,它強(qiáng)調(diào)的是CPU上線程(執(zhí)行序列)的切換以及對(duì)一個(gè)線程中任務(wù)執(zhí)行序列的一個(gè)中斷(中斷我們?cè)谶@里不深究了恤批,操作系統(tǒng)的核心機(jī)制)异吻。
并行、串行說的是一個(gè)時(shí)間點(diǎn)的概念,并發(fā)說的是一個(gè)時(shí)間段的概念诀浪,所以不同棋返。而且并發(fā)可以在并行和串行上轉(zhuǎn)換,讓我們看一下雷猪。在單核CPU上睛竣,有3個(gè)線程,每個(gè)線程需要3個(gè)時(shí)間片來完成(不考慮CPU上下文切換的時(shí)間求摇,雖然這個(gè)時(shí)間還真不一定可以忽略不計(jì))射沟,線程A執(zhí)行上了CPU執(zhí)行一個(gè)時(shí)間片后就下來了,然后第二個(gè)時(shí)間片線程C上去了与境,第二個(gè)時(shí)間片結(jié)束時(shí)验夯,線程C下來,然后第三個(gè)時(shí)間片線程B上去了∷さ螅現(xiàn)在三個(gè)時(shí)間片過去了挥转,線程A、B共屈、C都被執(zhí)行了绑谣,但是都沒執(zhí)行完,但是都被響應(yīng)了(聯(lián)想一下吞吐量)趁俊,這個(gè)過程是滿足并發(fā)的域仇,但是也滿足串行(在一個(gè)時(shí)間點(diǎn),真的就是只有一個(gè)線程在執(zhí)行)寺擂。在多核CPU上暇务,比如雙核,還是三個(gè)線程怔软,每個(gè)需要3個(gè)時(shí)間片來完成垦细。第一個(gè)時(shí)間片,線程A上了CPU1挡逼,線程C上了CPU2括改,等第一個(gè)時(shí)間片結(jié)束,線程A繼續(xù)在CPU1執(zhí)行家坎,但是線程C從CPU2上下來了嘱能,線程C上了CPU2。在這個(gè)時(shí)間段里面虱疏,有多個(gè)任務(wù)被執(zhí)行響應(yīng)惹骂,而且每個(gè)時(shí)刻,都真真正正有兩個(gè)線程在執(zhí)行做瞪,滿足并發(fā)对粪。
現(xiàn)在來回答多線程一定快嗎右冻?
這個(gè)需要分情況,情況依賴很多因素著拭,不過我們只需要舉出一個(gè)例子纱扭,證明不快就可以了。在單核CPU上儡遮,CPU因?yàn)檎{(diào)度多個(gè)線程執(zhí)行需要不斷的切換上下文乳蛾。在一個(gè)時(shí)間片快結(jié)束時(shí),CPU需要將當(dāng)前執(zhí)行的線程的狀態(tài)(就是一個(gè)臨時(shí)變量鄙币、PC等值)給記錄下來屡久,以備將來再次執(zhí)行這個(gè)線程時(shí),知道如何恢復(fù)此時(shí)的狀態(tài)(也叫恢復(fù)現(xiàn)場(chǎng))爱榔。所以,只要發(fā)生線程切換糙及,勢(shì)必就會(huì)有上下文切換详幽,說白了,線程切換就是上下文切換浸锨,執(zhí)行序列都在線程那里擺好了唇聘。上下文切換需要耗費(fèi)時(shí)間,一次保存現(xiàn)場(chǎng)柱搜,一次恢復(fù)現(xiàn)場(chǎng)迟郎。所以,一個(gè)任務(wù)如果從頭執(zhí)行到尾聪蘸,可能需要10個(gè)時(shí)間片宪肖,但中間經(jīng)歷了多次上下文切換,可以總的執(zhí)行時(shí)間要變成12個(gè)時(shí)間片了健爬。那為什么還要多線程呢控乾,因?yàn)橛脩趔w驗(yàn)好。這樣值得嗎娜遵?值得蜕衡,如果用戶體驗(yàn)不好,沒人用设拟,又有什么意義慨仿?客戶就是上帝,呵呵纳胧。
為什么需要多線程呢镰吆?
因?yàn)橛脩趔w驗(yàn)好,哈哈躲雅。