多核CPU
多核心cpu主要分原生多核和封裝多核。原生多核指的是真正意義上的多核,最早由AMD提出,每個(gè)核心之間都是完全獨(dú)立的,都擁有自己的前端總線,不會(huì)造成沖突,即使在高負(fù)載狀況下,每個(gè)核心都能保證自己的性能不受太大的影響,通俗的說,原生多核的抗壓能力強(qiáng),但是需要先進(jìn)的工藝,每擴(kuò)展一個(gè)核心都需要很多的研發(fā)時(shí)間。封裝多核是只把多個(gè)核心直接封裝在一起,比如Intel早期的PD雙核系列,就是把兩個(gè)單核直接封裝在一起,和原生的比起來還是差了很多,而且后者成本比較高,優(yōu)點(diǎn)在于多核心的發(fā)展要比原生快的多。
多進(jìn)程
Windows 應(yīng)用程序中消息有兩種送出途徑;直接和排隊(duì)。Windows或某些運(yùn)行的應(yīng)用程序可直接發(fā)布消息給窗口過程,或者,消息可送到消息列象連續(xù)不斷輪詢消息隊(duì)列的OS中當(dāng)前執(zhí)行的每個(gè)進(jìn)程都 事件驅(qū)動(dòng)程序不是由事件的順序來控制,而是由事件的發(fā)生來控,而事件的發(fā)生是隨機(jī)的、不確定的,這就允許程序的用戶用各種合理的順序來安排程序的流程。
多線程
線程(英語:multithreading),是指從軟件或者硬件上實(shí)現(xiàn)多個(gè)線程并發(fā)執(zhí)行的技術(shù)。具有多線程能力的計(jì)算機(jī)因有硬件支持而能夠在同一時(shí)間執(zhí)行多于一個(gè)線程,進(jìn)而提升整體處理性能。具有這種能力的系統(tǒng)包括對(duì)稱多處理機(jī)、多核心處理器以及芯片級(jí)多處理(Chip-level multithreading)或同時(shí)多線程(Simultaneous multithreading)處理器。在一個(gè)程序中,這些獨(dú)立運(yùn)行的程序片段叫作“線程”(Thread),利用它編程的概念就叫作“多線程處理(Multithreading)”。具有多線程能力的計(jì)算機(jī)因有硬件支持而能夠在同一時(shí)間執(zhí)行多于一個(gè)線程(***譯作“執(zhí)行緒”),進(jìn)而提升整體處理性能。
多核CPU、多進(jìn)程、多線程之間的聯(lián)系解析
多道程序設(shè)計(jì)
在進(jìn)程執(zhí)行過程中常常會(huì)因?yàn)橘Y源請(qǐng)求或者IO被阻塞或中斷(有的請(qǐng)求或者中斷需要處理很長(zhǎng)時(shí)間),此時(shí)CPU便空閑出來,眾所周知,CPU是計(jì)算機(jī)中非常寶貴的資源,為提高其利用率,操作系統(tǒng)需通過進(jìn)程切換,將CPU交給就緒隊(duì)列的某個(gè)進(jìn)程使用;等上次被阻塞或者中端的進(jìn)程再次滿足執(zhí)行條件(一般是請(qǐng)求的資源得到滿足或者IO完成等)后,操作系統(tǒng)便通過調(diào)度算法將CPU再次交給該進(jìn)程執(zhí)行任務(wù),其中操作系統(tǒng)的進(jìn)程調(diào)度算法有多種(例如在交互式系統(tǒng)(windows)中的進(jìn)程調(diào)度算法有時(shí)間片輪轉(zhuǎn)調(diào)度、優(yōu)先級(jí)調(diào)度、多級(jí)隊(duì)列調(diào)度等,這些相信大家都很熟悉了,此處不再進(jìn)一步闡述),具體選擇依賴操作系統(tǒng)。這時(shí)從用戶的角度感覺是多個(gè)進(jìn)程在同時(shí)執(zhí)行,這的易于操作系統(tǒng)通過進(jìn)程調(diào)度將一個(gè)cpu變成多個(gè)虛擬的CPU,實(shí)現(xiàn)多個(gè)進(jìn)程的偽并發(fā)。在《現(xiàn)在操作系統(tǒng)》中將這種進(jìn)程間的切換稱之為“多道程序設(shè)計(jì)”。
?。ㄗⅲ好總€(gè)進(jìn)程在執(zhí)行過程中表現(xiàn)了不同的形態(tài),CPU需要根據(jù)進(jìn)程執(zhí)行過程中的特性制定CPU調(diào)度算法從而提高CPU利用率)
進(jìn)程切換:由于每個(gè)進(jìn)程的處理任務(wù)異樣性,其進(jìn)程的輸入、輸出、處理過程、處理狀態(tài)的都不同,那在進(jìn)程切換的過程中是否也應(yīng)該考慮這些參數(shù)呢?答案是肯定的。一個(gè)正在執(zhí)行的進(jìn)程包括程序計(jì)數(shù)器、寄存器、變量的當(dāng)前值等,而這些數(shù)據(jù)都是保存在CPU的寄存器中的,且這些寄存器只能是正在使用CPU的進(jìn)程才能享用,所以在進(jìn)程切換時(shí),首先得保存上一個(gè)進(jìn)程的這些數(shù)據(jù)(便于下次獲得CPU的使用權(quán)時(shí)從上次的中斷處開始繼續(xù)順序執(zhí)行,而不是返回到進(jìn)程開始,否則每次進(jìn)程重新獲得CPU時(shí)所處理的任務(wù)都是上一次的重復(fù),可能永遠(yuǎn)也到不了進(jìn)程的結(jié)束出,因?yàn)橐粋€(gè)進(jìn)程幾乎不可能執(zhí)行完所有任務(wù)后才釋放CPU),然后將本次獲得CPU的進(jìn)程的這些數(shù)據(jù)裝入CPU的寄存器從上次斷點(diǎn)處繼續(xù)執(zhí)行剩下的任務(wù)。操作系統(tǒng)為了便于管理系統(tǒng)內(nèi)部進(jìn)程,為每個(gè)進(jìn)程創(chuàng)建了一張進(jìn)程表項(xiàng),如表1所示。
?。ㄗⅲ篊PU的并發(fā)需求產(chǎn)生了進(jìn)程,進(jìn)程執(zhí)行過程中的特性產(chǎn)生了CPU調(diào)度算法,CPU調(diào)度時(shí)需要維護(hù)每個(gè)進(jìn)程特有的數(shù)據(jù)和空間,因此產(chǎn)生了維護(hù)每個(gè)進(jìn)程的進(jìn)程表項(xiàng))
多道程序設(shè)計(jì)的基本知識(shí)回顧差不多了,下慢我們來探討下多道程序設(shè)計(jì)模型。
從上面的分析可以得知,多道程序設(shè)計(jì)可以提高cpu的利用率。但嚴(yán)格來講,如果進(jìn)程的計(jì)算平均時(shí)間是進(jìn)程在內(nèi)存中停留時(shí)間的20%,且內(nèi)存中同時(shí)有5個(gè)進(jìn)程,則CPU將一直處于滿負(fù)荷狀態(tài),然而在模擬在實(shí)際中過于樂觀,因?yàn)槠浼僭O(shè)這5個(gè)進(jìn)程不會(huì)同時(shí)等待IO。
下面我們從概率的角度分析CPU的利用率,假設(shè)進(jìn)程等待IO操作的時(shí)間與其停留內(nèi)存的時(shí)間比例為p,當(dāng)內(nèi)存有n個(gè)進(jìn)程時(shí),則n個(gè)進(jìn)程同時(shí)等待IO的概率為pn。則CPU的利用率為:
CPU的利用率 = 1 - pn
圖1以n為變量的函數(shù)表示了CPU的利用率,n為多道程序設(shè)計(jì)的道數(shù)。
從圖中可以看出當(dāng)進(jìn)程花80%進(jìn)行IO時(shí)(IO密集型),需要大約10個(gè)進(jìn)程并發(fā)才能使CPU得到充分利用;而當(dāng)進(jìn)程只花20%的時(shí)間進(jìn)行IO時(shí)(稱CPU密集型),孩子需要2個(gè)進(jìn)程就可以使CPU的浪費(fèi)率低于10%。在實(shí)際的應(yīng)用中,不管一個(gè)等待用戶從終端輸入的交互式進(jìn)程還是做大量讀寫磁盤的服務(wù)器進(jìn)程80%甚至更多的IO時(shí)間是普遍的,所以通過多道程序設(shè)計(jì)模式可以提高IO密集型進(jìn)程的CPU利用率,從而間接提高了整個(gè)系統(tǒng)的吞吐量;而對(duì)于CPU密集型進(jìn)程,其并發(fā)度與CPU利用率不一定是成真比例。這套標(biāo)準(zhǔn)體系對(duì)與多線程同樣適用,我們稍后進(jìn)一步分析。
多道程序設(shè)計(jì)就回顧到這里,可見其核心就是通過進(jìn)程調(diào)度提高CPU的利用率,將一個(gè)CPU虛擬成多個(gè),實(shí)現(xiàn)多個(gè)進(jìn)程的并發(fā)執(zhí)行,至于進(jìn)程如何創(chuàng)建、銷毀、以及狀態(tài)和狀態(tài)轉(zhuǎn)換、進(jìn)程的層次結(jié)構(gòu)以及進(jìn)程的實(shí)現(xiàn),此處就不闡述了,如果答不上或者不能隨手捻來的話,還是回去看看《現(xiàn)代操作系統(tǒng)》這本書吧。
?。ㄗⅲ哼M(jìn)程可以分為I/O密集型和CPU密集型,根據(jù)進(jìn)程的不同特性設(shè)置進(jìn)程的策略,來提高CPU利用率,方法不是一成不變的)
下面我們就一起談?wù)劸€程的相關(guān)知識(shí)以及與進(jìn)程的關(guān)系。當(dāng)你讀到這里,有的同鞋肯定會(huì)問,既然多道程序設(shè)計(jì)可以提高CPU的利用率,并實(shí)現(xiàn)多個(gè)進(jìn)程的并發(fā)執(zhí)行。如果你在提這個(gè)問題,表示你在思考,如果你還沒有意識(shí)到這個(gè)問題,建議你停下結(jié)合之前學(xué)習(xí)的知識(shí)先想一想,看看是否自己能給出一個(gè)答案?
線程
我們先看看維基百科對(duì)線程的定義:線程(英語:thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。它被包含在進(jìn)程之中,是行程中的實(shí)際運(yùn)作單位。一條線程指的是進(jìn)程中一個(gè)單一順序的控制流,一個(gè)進(jìn)程中可以並行多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù)。在Unix System V及SunOS中也被稱為輕量進(jìn)程(lightweight processes),但輕量進(jìn)程更多指內(nèi)核線程(kernel thread),而把用戶線程(user thread)稱為線程。此外,從資源分配的角度看,進(jìn)程是資源所有資源分配的基本單位,線程則是CPU調(diào)度的基本單位,即使在單線程進(jìn)程中也是如此。
引入線程的原因:
1) 一個(gè)應(yīng)用程序中同時(shí)存在多個(gè)任務(wù),其中的部分活動(dòng)會(huì)隨時(shí)間的推移而阻塞,而另外一部分則不會(huì),例如,一個(gè)文字處理軟件,前臺(tái)部分需要從終端設(shè)備獲得輸入或者將處理完的部分輸出,而后臺(tái)線程則可以實(shí)現(xiàn)對(duì)文字的處理。故對(duì)于CPU密集型進(jìn)程,該用多線程其性能不一定能得到很大提高,但對(duì)于IO密集型進(jìn)程,其性能可得到很大提高。
2) 線程比進(jìn)程更輕量級(jí),創(chuàng)建和撤銷的代價(jià)小,在許多系統(tǒng)中,創(chuàng)建一個(gè)線程比一個(gè)進(jìn)程要快10~100倍不等。
3) 在多核CPU中,真正的并行有了可能。即在多線程設(shè)計(jì)中一部分可用來處理前臺(tái)任務(wù),一部分可用來處理后臺(tái)任務(wù),實(shí)現(xiàn)真正意義上的并行。
4) 線程間的切換代價(jià)要比進(jìn)程切換的代價(jià)小。
引入多線程的原因:
1)某個(gè)操作可能會(huì)陷入長(zhǎng)時(shí)間等待,等待的線程會(huì)進(jìn)入睡眠狀態(tài),無法繼續(xù)執(zhí)行。多線程執(zhí)行可以有效利用等待時(shí)間。如等待網(wǎng)絡(luò)響應(yīng)可能需要幾秒的時(shí)間。
2)某個(gè)操作(常常是計(jì)算)會(huì)消耗大量的時(shí)間,如果只有一個(gè)線程,程序和用戶之間的交互會(huì)中斷。多線程可以讓一個(gè)線程負(fù)責(zé)交付,另一個(gè)線程負(fù)責(zé)計(jì)算。
3)多CPU或者多核計(jì)算機(jī),本身具備同時(shí)執(zhí)行多個(gè)線程的能力,故單線程無法完全發(fā)揮計(jì)算機(jī)的計(jì)算能力。
4)相對(duì)于多進(jìn)程應(yīng)用,多線程在數(shù)據(jù)共享方面效率要高很多。
5)程序邏輯本身就要求并發(fā)操作。
現(xiàn)在我們通過考察一個(gè)例子,就可以更清楚看出多線程的有益之處了。
假設(shè)用戶正在編輯一本書。對(duì)于編輯這來說,最容易的辦法是把正本書作為一個(gè)文件,便于編輯;而對(duì)于計(jì)算機(jī)來說把每個(gè)章節(jié)作為一個(gè)文件處理起來更快,但對(duì)于編輯者來說修改就太麻煩了,因?yàn)橛械男薷牟恢乖O(shè)計(jì)一個(gè)章節(jié)而是整本書,例如在整本書中替換某個(gè)詞或字等等,如果整本書作為一個(gè)文件,正樣處理就方便多了。否則,就得對(duì)每個(gè)章節(jié)所在文件進(jìn)行處理。
現(xiàn)在如果用在一個(gè)1000頁的文檔中刪除第一頁的某一行的某個(gè)詞,為保證格式的正確性,字處理軟件需要對(duì)文檔進(jìn)行格式處理。但此時(shí)用戶需要立刻跳到地800也進(jìn)行另外一處修改,于是字處理軟件被強(qiáng)制對(duì)整個(gè)書的前800頁進(jìn)程格式處理,因?yàn)樵谂帕性擁撉懊娴乃许撁嬷?,字處理軟件并不知道?00頁的第一行應(yīng)該在哪里。而在第800也的頁面可以顯示在屏幕之前,計(jì)算機(jī)可能要拖延想當(dāng)長(zhǎng)一段時(shí)間進(jìn)行處理,從而令用戶不甚滿意。
此時(shí),多線程便可以有用武之地了。假設(shè)字處理軟件編寫成含有兩個(gè)線程的程序。一個(gè)線程處理用戶的交互,另一個(gè)用來在后臺(tái)進(jìn)行格式處理。一旦第一頁發(fā)生的修改,交互線程就立即同時(shí)后臺(tái)格式處理線程重現(xiàn)整理整本書的格式。同時(shí),交互式線程繼續(xù)監(jiān)控用戶的鼠標(biāo)、鍵盤,并響應(yīng)諸如第一頁之類的簡(jiǎn)單命令,此刻,后臺(tái)線程正在進(jìn)行瘋狂的運(yùn)算,如果運(yùn)氣好的話,格式整理可能在用戶請(qǐng)求查看第800頁之前完成,這樣用戶就感覺不到延遲了。
同理,為保證用戶的編輯工作得到及時(shí)保存,可以在添加一個(gè)現(xiàn)場(chǎng)周期性對(duì)文件進(jìn)現(xiàn)場(chǎng)可以處理磁盤備份,而不必干擾其他兩個(gè)線程。擁有三個(gè)線程的情形如圖2所示。
圖2 三個(gè)線程的字處理軟件
試想,如果是單線程的話,那么在進(jìn)行磁盤備份的時(shí),來自鍵盤或者鼠標(biāo)的命令就會(huì)被忽略,直至備份完成。有的同鞋會(huì)說,可以引入中斷機(jī)制來中止備份操作,相應(yīng)鼠標(biāo)和鍵盤的命令,但其復(fù)雜性可想而知。如果引入三個(gè)線程,其設(shè)計(jì)就簡(jiǎn)單多了,一個(gè)線程用于與用戶交互,第二線程在得到地一個(gè)線程的通知后在后臺(tái)進(jìn)行文檔的格式化處理,第三個(gè)線程則周期性將ARM內(nèi)的內(nèi)容被封到磁盤。
此處,很顯然,這里用三個(gè)不同的進(jìn)程是不能工作的,因?yàn)槿齻€(gè)線程都需要在同一個(gè)文件上進(jìn)行操作,通過三個(gè)線程,由于一個(gè)進(jìn)程內(nèi)的所有線程共享公共內(nèi)存,于是便可以在同一文件上進(jìn)行處理。同理,其他的交互式程序也可以采用同樣的設(shè)計(jì)方法。
看完這個(gè)例子,部分對(duì)多道程序設(shè)計(jì)比較忠心的同學(xué)可能會(huì)問,上述三個(gè)線程能協(xié)同完成工作,主要的便利之處在于其共享了進(jìn)程中的公共內(nèi)存空間。同樣,也可以采用進(jìn)程通信的方式來協(xié)同完成工作?答案確實(shí)如此,但仔細(xì)思考幾個(gè)問題:1、進(jìn)程通信與線程通信的代價(jià)孰高孰第?2、進(jìn)程切換和線程切換的代價(jià)?3、如何保證三個(gè)進(jìn)程所處理內(nèi)容的一致性?而多線程方案中由于都是對(duì)同一文檔內(nèi)容進(jìn)行處理,其一致性的保證則簡(jiǎn)單很多。如果能準(zhǔn)確解答上述幾個(gè)答案,為什么不選擇多道程序設(shè)計(jì)方案來完成其上述工作的原因就不攻自破了吧。
線程的內(nèi)容我們回顧差不多了,現(xiàn)在我們來一起看看進(jìn)程與線程的關(guān)系和區(qū)別吧。
進(jìn)程與線程:
進(jìn)程是操作系統(tǒng)的管理單位,而線程則是進(jìn)程的管理單位;一個(gè)線程至少包含一個(gè)執(zhí)行線程。不管是在單線程還是多線程中,每個(gè)線程都有一個(gè)程序計(jì)數(shù)器(記錄要執(zhí)行的下一條指令),一組寄存器(保存當(dāng)前線程的工作變量),堆棧(記錄執(zhí)行歷史,其中每一幀保存了一個(gè)已經(jīng)調(diào)用但為返回的過程)。雖然線程寄生在進(jìn)程中,但與他的進(jìn)程是不同的概念,并且可以分別處理:進(jìn)程是系統(tǒng)分配資源的基本單位,線程時(shí)調(diào)度CPU的基本單位。
多線程是對(duì)多進(jìn)程的模擬。前者,多個(gè)線程共享同一個(gè)地址空間和其他資源,后者共享物理內(nèi)存、磁盤、IO等其他資源,故線程被稱為“輕量級(jí)進(jìn)程”。多線程在但CPU系統(tǒng)中運(yùn)行時(shí),線程輪流運(yùn)行,猶如多道程序設(shè)計(jì),制造線程并行運(yùn)行的假象。在一個(gè)有三個(gè)CPU密集型的進(jìn)程中,實(shí)際上每個(gè)線程在一個(gè)CPU上得到的真實(shí)CPU速度的三分之一。不過隨著技術(shù)的發(fā)展,目前主流的CPU都已經(jīng)直接硬件支持多線程,并允許線程在幾個(gè)納秒級(jí)內(nèi)完成切換。后續(xù)會(huì)對(duì)多進(jìn)程、多線程、以及多核之間的關(guān)系進(jìn)行總結(jié)。
線程間不像進(jìn)程之間那樣存在很大的獨(dú)立性,一個(gè)進(jìn)程的多個(gè)線程共享進(jìn)程內(nèi)部的很多資源,線程間可以互寫對(duì)方的堆棧,而不同的進(jìn)程則無法對(duì)其他進(jìn)程的地址空間進(jìn)行寫操作。因此,在實(shí)現(xiàn)多線程編程中,應(yīng)設(shè)計(jì)合理的同步通信機(jī)制,避免數(shù)據(jù)沖突的現(xiàn)象發(fā)生。圖3給出了進(jìn)程、線程的內(nèi)容,其中進(jìn)程的內(nèi)容是該進(jìn)程的所有線程共享的。
評(píng)論