久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

JAVA多線程(一)基本概念和上下文切換性能損耗

 紀(jì)平aa8woyo5no 2017-03-22

1 多線程概念

在理解多線程之前,,我們先搞清楚什么是線程。根據(jù)維基百科的描述,,線程是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位,。它被包含在進(jìn)程之中,是行程中的實(shí)際運(yùn)行單位,。一條線程指的是進(jìn)程中一個(gè)單一順序的控制流,,一個(gè)進(jìn)程中可以并行多個(gè)線程,每條線程并行執(zhí)行不同的任務(wù),。每個(gè)線程共享堆空間,,擁有自己獨(dú)立的棧空間,。

這里反復(fù)出現(xiàn)的概念是線程和進(jìn)程,我們?cè)谶@里列出它們的區(qū)別:

  • 線程劃分尺度小于進(jìn)程,,線程隸屬于某個(gè)進(jìn)程,;
  • 進(jìn)程是CPU、內(nèi)存等資源占用的基本單位,,線程是不能獨(dú)立占有這些資源的,;
  • 進(jìn)程之間相互獨(dú)立,通信比較困難,,而線程之間共享一塊內(nèi)存區(qū)域,,通信方便,;
  • 進(jìn)程在執(zhí)行過(guò)程中,包含比較固定的入口,、執(zhí)行順序和出口,,而進(jìn)程的這些過(guò)程會(huì)被應(yīng)用程序控制。

多線程是指從軟件或者硬件上實(shí)現(xiàn)多個(gè)線程并發(fā)執(zhí)行的技術(shù),。具有多線程能力的計(jì)算機(jī)因有硬件支持而能夠在同一時(shí)間執(zhí)行多個(gè)線程,,進(jìn)而提升整體處理效能。

2 為什么要使用多線程

隨著計(jì)算機(jī)硬件的發(fā)展,,多核CPU已經(jīng)屢見(jiàn)不鮮了,,甚至手機(jī)處理器都早已是多核的天下。這就給我們使用多線程提供了硬件基礎(chǔ),,但是,,只是因?yàn)橛布屛覀兛梢詫?shí)現(xiàn)多線程,就要這樣做嗎,?一起來(lái)看看多線程的優(yōu)點(diǎn):

  • 更高的運(yùn)行效率,。在多核CPU上,線程之間是互相獨(dú)立的,,不用互相等待,,也就是所謂的“并行“。舉個(gè)例子,,一個(gè)使用多線程的文件系統(tǒng)可以實(shí)現(xiàn)高吞吐量和低延遲,。這是因?yàn)槲覀兛梢杂靡粋€(gè)線程來(lái)檢索存儲(chǔ)在高速介質(zhì)(例如高速緩沖存儲(chǔ)器)中的數(shù)據(jù),另一個(gè)線程檢索低速介質(zhì)(例如外部存儲(chǔ))中的數(shù)據(jù),,二者互不干擾,,也不用等到另一個(gè)線程結(jié)束才執(zhí)行;
  • 多線程是模塊化的編程模型,。在單線程中,,如果主執(zhí)行線程在一個(gè)耗時(shí)較長(zhǎng)的任務(wù)上卡住,或者因?yàn)榫W(wǎng)絡(luò)響應(yīng)問(wèn)題陷入長(zhǎng)時(shí)間等待,,此時(shí)程序不會(huì)響應(yīng)鼠標(biāo)和鍵盤(pán)等操作,。多線程通過(guò)將程序分成幾個(gè)功能相對(duì)獨(dú)立的模塊,單獨(dú)分配一個(gè)線程去執(zhí)行這個(gè)長(zhǎng)耗時(shí)任務(wù),,不影響其它線程的執(zhí)行,,就可以避免這個(gè)問(wèn)題;
  • 與進(jìn)程相比,,線程的創(chuàng)建和切換開(kāi)銷更小,。使用多線程為多個(gè)客戶端服務(wù),比使用多進(jìn)程消耗的資源少得多。由于啟動(dòng)一個(gè)新的線程必須給這個(gè)線程分配獨(dú)立的地址空間,,建立許多數(shù)據(jù)結(jié)構(gòu)來(lái)維護(hù)線程代碼段,、數(shù)據(jù)段等信息,而運(yùn)行于同一進(jìn)程內(nèi)的線程共享代碼段,、數(shù)據(jù)段,,線程的啟動(dòng)和切換開(kāi)銷小得多。一個(gè)典型的應(yīng)用例子就是Apache HTTP服務(wù)器所使用的線程池: 一個(gè)監(jiān)聽(tīng)線程池專門(mén)用來(lái)監(jiān)聽(tīng)是否有請(qǐng)求進(jìn)入,,另一個(gè)服務(wù)器線程池用來(lái)處理這些請(qǐng)求,;
  • 通信方便。因?yàn)榫€程共享?xiàng),?臻g,,可以通過(guò)線程之間共享的數(shù)據(jù)、代碼和文件來(lái)進(jìn)行線程之間的通信(詳見(jiàn)我的另一篇JAVA多線程(四)數(shù)據(jù)共享),。相比之下,,進(jìn)程之間的通信則需要專門(mén)的消息傳遞機(jī)制;
  • 使用多線程能簡(jiǎn)化程序的結(jié)構(gòu),,使程序便于理解和維護(hù),。一個(gè)復(fù)雜的進(jìn)程可以分成多個(gè)線程來(lái)執(zhí)行;
  • 更高的資源利用率,。多CPU或多核計(jì)算機(jī)本來(lái)就具有執(zhí)行多線程的能力,,如果只使用單個(gè)線程,將無(wú)法重復(fù)利用計(jì)算機(jī)資源,,造成巨大浪費(fèi),。

3 多線程上下文切換的性能損耗

前面夸了多線程的優(yōu)點(diǎn),凡事都有兩面性,,使用多線程也有弊端,。盡管使用多線程往往可以獲得更大的吞吐率和更短的響應(yīng)時(shí)間,但是,,多線程程序不一定比單線程程序執(zhí)行速度快,。很多線程存在情況下,線程之間的切換會(huì)非常頻繁,,切換帶來(lái)的性能損耗是非??捎^的。

3.1 上下文切換的概念

先來(lái)解釋一下什么是上下文切換(context switch),。在多任務(wù)處理系統(tǒng)中,,作業(yè)數(shù)通常大于CPU數(shù)。為了讓用戶覺(jué)得這些任務(wù)在同時(shí)進(jìn)行,,CPU給每個(gè)任務(wù)分配一定時(shí)間,把當(dāng)前任務(wù)狀態(tài)保存下來(lái),當(dāng)前運(yùn)行任務(wù)轉(zhuǎn)為就緒(或者掛起,、刪除)狀態(tài),,另一個(gè)被選定的就緒任務(wù)成為當(dāng)前任務(wù)。之后CPU可以回過(guò)頭再處理之前被掛起任務(wù),。上下文切換就是這樣一個(gè)過(guò)程,,它允許CPU記錄并恢復(fù)各種正在運(yùn)行程序的狀態(tài),使它能夠完成切換操作,。在這個(gè)過(guò)程中,,CPU會(huì)停止處理當(dāng)前運(yùn)行的程序,并保存當(dāng)前程序運(yùn)行的具體位置以便之后繼續(xù)運(yùn)行,。

上下文切換在不同的場(chǎng)合有不同的含義,,在下表中列出:

上下文切換種類 描述
線程切換 同一進(jìn)程中的兩個(gè)線程之間的切換
進(jìn)程切換 兩個(gè)進(jìn)程之間的切換
模式切換 在給定線程中,用戶模式和內(nèi)核模式的切換
地址空間切換 將虛擬內(nèi)存切換到物理內(nèi)存

根據(jù)種類的不同,,切換時(shí)造成的性能消耗也不同,。

究竟什么時(shí)候會(huì)發(fā)生上下文切換?總共有三種情況:

上下文切換發(fā)生條件 描述
中斷處理 中斷分為硬件中斷和軟件中斷,,軟件中斷包括因?yàn)镮O阻塞,、未搶到資源或者用戶代碼等原因,線程被掛起
多任務(wù)處理 每個(gè)程序都有相應(yīng)的處理時(shí)間片,,當(dāng)前任務(wù)的時(shí)間片用完之后,,系統(tǒng)CPU正常調(diào)度下一個(gè)任務(wù)
用戶態(tài)切換 這種情況下,上下文切換并非一定發(fā)生,,只在特定操作系統(tǒng)才會(huì)發(fā)生上下文切換

3.2 上下文切換的步驟

為了理解為什么上下文切換的時(shí)候會(huì)損耗性能,,我們應(yīng)該先看看上下文切換的過(guò)程中究竟發(fā)生了什么。在切換過(guò)程中,,正在執(zhí)行的進(jìn)程的狀態(tài)必須以某種方式存儲(chǔ)起來(lái),,這樣在未來(lái)才能被恢復(fù)。這里說(shuō)的進(jìn)程狀態(tài)包括該進(jìn)程正在使用的所有寄存器(尤其是程序計(jì)數(shù)器),,和一些必要的操作系統(tǒng)數(shù)據(jù),。保存進(jìn)程狀態(tài)的數(shù)據(jù)結(jié)構(gòu)叫做“進(jìn)程控制塊”(PCB,process control block);

PCB通常是系統(tǒng)內(nèi)存占用區(qū)中的一個(gè)連續(xù)存區(qū),,它存放著操作系統(tǒng)用于描述進(jìn)程情況及控制進(jìn)程運(yùn)行所需的全部信息,,它使一個(gè)在多道程序環(huán)境下不能獨(dú)立運(yùn)行的程序成為一個(gè)能獨(dú)立運(yùn)行的基本單位或一個(gè)能與其他進(jìn)程并發(fā)執(zhí)行的進(jìn)程。

上下文切換的具體步驟是(假設(shè)當(dāng)前進(jìn)程是進(jìn)程A,,要切換到的下一個(gè)進(jìn)程是進(jìn)程B):

  1. 保存進(jìn)程A的狀態(tài)(寄存器和操作系統(tǒng)數(shù)據(jù)),;
  2. 更新PCB中的信息,對(duì)進(jìn)程A的“運(yùn)行態(tài)”做出相應(yīng)更改,;
  3. 將進(jìn)程A的PCB放入相關(guān)狀態(tài)的隊(duì)列,;
  4. 將進(jìn)程B的PCB信息改為“運(yùn)行態(tài)”,,并執(zhí)行進(jìn)程B;
  5. B執(zhí)行完后,,從隊(duì)列中取出進(jìn)程A的PCB,,恢復(fù)進(jìn)程A被切換時(shí)的上下文,繼續(xù)執(zhí)行A,。

線程分為用戶級(jí)線程和內(nèi)核級(jí)線程,。同一進(jìn)程中的用戶級(jí)線程切換的時(shí)候,只需要保存用戶寄存器的內(nèi)容,,程序計(jì)數(shù)器,,棧指針,不需要模式切換,。但是這樣會(huì)導(dǎo)致線程阻塞和無(wú)法利用多處理器,。而同一進(jìn)程中的內(nèi)核級(jí)線程切換的時(shí)候,就克服了這兩個(gè)缺點(diǎn),,但是除了保存上下文,,還要進(jìn)行模式切換。

線程切換和進(jìn)程切換的步驟也不同,。進(jìn)程的上下文切換分為兩步:1.切換頁(yè)目錄以使用新的地址空間,;2.切換內(nèi)核棧和硬件上下文。對(duì)于Linux來(lái)說(shuō),,線程和進(jìn)程的最大區(qū)別就在于地址空間,。對(duì)于線程切換,第1步是不需要做的,,第2是進(jìn)程和線程切換都要做的,。所以明顯是進(jìn)程切換代價(jià)大。線程上下文切換和進(jìn)程上下文切換一個(gè)最主要的區(qū)別是線程的切換虛擬內(nèi)存空間依然是相同的,,但是進(jìn)程切換是不同的,。這兩種上下文切換的處理都是通過(guò)操作系統(tǒng)內(nèi)核來(lái)完成的。內(nèi)核的這種切換過(guò)程伴隨的最顯著的性能損耗是將寄存器中的內(nèi)容切換出,。

3.3 上下文切換帶來(lái)的損耗

根據(jù)前面的切換步驟,,我們可以很容易得到性能損耗的原因。

上下文切換會(huì)導(dǎo)致CPU在寄存器和運(yùn)行隊(duì)列之間來(lái)回奔波,。這種消耗可以分為兩種

損耗種類 描述
直接損耗 CPU寄存器需要保存和加載, 系統(tǒng)調(diào)度器的代碼需要執(zhí)行, TLB實(shí)例需要重新加載, CPU 的pipeline需要刷掉
間接損耗 多核的cache之間得共享數(shù)據(jù)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多