java学生背景知识要求,好好学习Java并发 一、背景知识
并發(fā)指一個(gè)處理器同時(shí)處理多個(gè)任務(wù),但這個(gè)定義只是從宏觀上來講的。舉個(gè)生活中的例子來說明,一個(gè)電商小二同時(shí)接待兩個(gè)客戶,小二通常的做法是在和A客戶聊的間隙回復(fù)B客戶的問題,和B客戶聊的間隙又回復(fù)A客戶的問題,這樣看起來小二同時(shí)服務(wù)了A和B,但是具體到某次答復(fù),小二只是在為一個(gè)客戶服務(wù)。那么對(duì)應(yīng)到計(jì)算機(jī)上,并發(fā)是怎樣發(fā)生的呢?
計(jì)算機(jī)的CPU通過給每個(gè)線程分配時(shí)間片來實(shí)現(xiàn)并發(fā)。時(shí)間片是CPU分配給各個(gè)線程的時(shí)間,每個(gè)線程被分配一個(gè)時(shí)間段,該線程在這個(gè)時(shí)間段擁有CPU的執(zhí)行權(quán),這個(gè)時(shí)間段就成為時(shí)間片。如果在時(shí)間片結(jié)束時(shí)線程還在運(yùn)行,則CPU將被剝奪并分配給另一個(gè)線程。如果線程在時(shí)間片結(jié)束前阻塞或結(jié)束,則CPU當(dāng)即進(jìn)行切換,而不會(huì)造成CPU資源的浪費(fèi)。這樣,宏觀上看有多個(gè)線程在并行進(jìn)行;但是從微觀上看,由于只有一個(gè)CPU,一次只能處理一個(gè)線程線的一小段指令。
說到這里,似乎忽略了一個(gè)問題,為什么要引進(jìn)并發(fā)呢?仍以上面的電商小二為例,在串行模式下小二先服務(wù)客戶A,等對(duì)客戶A的服務(wù)完成之后再對(duì)客戶B進(jìn)行服務(wù),這樣小二和客戶溝通中的時(shí)間空隙時(shí)間就白白流失掉了,串行模式的效率低于并發(fā)模式。另外并發(fā)模型更能滿足復(fù)雜業(yè)務(wù)的需要,因?yàn)椴l(fā)模型能更好的模擬現(xiàn)實(shí)中的問題 。所以引進(jìn)并發(fā)是很有必要的 。
接下來了解一些計(jì)算機(jī)的知識(shí),為后面學(xué)習(xí)Java并發(fā)做鋪墊。
1. 高速緩存
計(jì)算機(jī)執(zhí)行的任務(wù)大體上分為在CPU上計(jì)算和在內(nèi)存上存取數(shù)據(jù)兩部分。然而計(jì)算機(jī)執(zhí)行任務(wù)依賴的兩個(gè)硬件、CPU和內(nèi)存在性能上差距有幾個(gè)數(shù)量級(jí)之大,而且短時(shí)間內(nèi)內(nèi)存性能的不足是彌補(bǔ)不了,于是工程師采用優(yōu)化運(yùn)行流程來解決問題。工程師在計(jì)算機(jī)系統(tǒng)加入一層的高速緩存(讀寫速度幾乎接近CPU的運(yùn)算速度)來作為內(nèi)存與CPU之間的緩沖。這樣可以將計(jì)算使用的數(shù)據(jù)復(fù)制到緩存中,CPU運(yùn)行時(shí)直接操作緩存中的數(shù)據(jù),當(dāng)運(yùn)算結(jié)束后再將數(shù)據(jù)從緩存同步回內(nèi)存之中,這樣避免了CPU在運(yùn)行的過程中長時(shí)間停止來等待從內(nèi)存中讀寫數(shù)據(jù)了。
高速緩存彌補(bǔ)了CPU的執(zhí)行速度和內(nèi)存存取速度差距,但是也造成了新的問題:緩存一致性問題。在多核CPU系統(tǒng)中,每個(gè)核都有自己的高速緩存,同時(shí)這多個(gè)核共用一個(gè)主內(nèi)存。這樣就可能發(fā)生一種情況:一個(gè)以上的CPU緩存了同一個(gè)主內(nèi)存上的某個(gè)數(shù)據(jù),CPU各自獨(dú)立的操作自己緩存的數(shù)據(jù),結(jié)果主內(nèi)存的某個(gè)數(shù)據(jù)在不同的CPU中的緩存值卻是不一樣的。
既然高速緩存方案已經(jīng)廣泛使用了,緩存一致性問題也一定得到了解決。這個(gè)解決方案是要求處理器在訪問緩存時(shí)遵循特定的協(xié)議,這類型的協(xié)議有很多,如MESI協(xié)議:當(dāng)CPU寫數(shù)據(jù)時(shí),如果發(fā)現(xiàn)操作的變量是共享變量,即在其他CPU緩存中也存在該變量的副本,會(huì)發(fā)出信號(hào)通知它們將該變量的緩存行置為無效狀態(tài),當(dāng)其他CPU需要讀取這個(gè)變量時(shí),發(fā)現(xiàn)自己緩存的該變量的副本是無效的,它就會(huì)從內(nèi)存重新讀取。
仔細(xì)看MESI協(xié)議的原理,好像最終也沒能讓緩存保持一致,而是讓CPU及時(shí)發(fā)現(xiàn)緩存的不一致,并且讓不一致的緩存失效,有點(diǎn)兒兜底方案的感覺。
2. CPU的工作模式
一條計(jì)算機(jī)指令的執(zhí)行一般可以可以分為以下幾個(gè)步驟:
取指 IF
譯碼和取寄存器操作數(shù) ID
執(zhí)行或者有效地址計(jì)算 EX
存儲(chǔ)器訪問 MEM
寫回 WB
這些步驟執(zhí)行的過程中用到的是不同的硬件,比如,取指用到的是PC寄存器和存儲(chǔ)器,譯碼時(shí)用到的是指令寄存器組,執(zhí)行時(shí)會(huì)使用ALU(算數(shù)邏輯單元)。基于這一特點(diǎn),工程師發(fā)明了流水線技術(shù)來執(zhí)行指令。這樣指令的執(zhí)行順序?qū)⒉辉偈谴械?#xff0c;不會(huì)因?yàn)橐粭l指令卡在某個(gè)階段而影響后面指令的執(zhí)行,只要CPU內(nèi)部相應(yīng)的處理部件未被占滿就可以不停的執(zhí)行指令,這樣CPU的使用效率就會(huì)非常高。
但是,這也會(huì)帶來一個(gè)問題,后面執(zhí)行的指令可能會(huì)比在它之前執(zhí)行的指令完成的早,從而造成一種亂序,因?yàn)槟承┲噶钤贓X階段耗時(shí)比較長的現(xiàn)象常有發(fā)生。這就是所謂的"順序流入,亂序流出"。
另外,現(xiàn)代處理器引入了寫緩存優(yōu)化。處理器使用寫緩沖區(qū)臨時(shí)保存向內(nèi)存寫入的數(shù)據(jù),而不是直接將數(shù)據(jù)寫入內(nèi)存,然后采用批處理的方式刷新寫緩沖區(qū)將數(shù)據(jù)批量寫入內(nèi)存,而且會(huì)合并寫緩沖區(qū)中對(duì)同一內(nèi)存地址的多次寫。這樣既可以可以保證指令流水線持續(xù)運(yùn)行,同時(shí)也減少對(duì)內(nèi)存總線的占用。
現(xiàn)在我們看另一種情況,有A、B、C、D四條依次執(zhí)行的指令,其中B指令的執(zhí)行需要依賴A的計(jì)算結(jié)果,這時(shí)候B指令就要停頓在某個(gè)階段,等待A執(zhí)行完成后才能執(zhí)行,C和D正常執(zhí)行。想一想有沒有辦法縮短B指令執(zhí)行過程中的停頓時(shí)間?肯定是有的,因?yàn)锽和CD之間沒有關(guān)聯(lián),可以把B放在C和D之后執(zhí)行,這樣等B開始執(zhí)行的時(shí)候說不定A已經(jīng)執(zhí)行完成了,CPU不需要停頓,這樣CPU的使用效率又有所提高。
事實(shí)上,現(xiàn)在很多語言也是這么做的,在編譯階段保證上下文前提的下會(huì)對(duì)指令進(jìn)行重排,以提高CPU的處理性能。
3. 原子操作的實(shí)現(xiàn)原理
原子本意是"不能被進(jìn)一步分割的最小粒子",而原子操作意為"不可被中斷的一個(gè)或一系列操作"。在多處理器上實(shí)現(xiàn)原子操作有點(diǎn)兒復(fù)雜,下面看下Intel處理器是如何實(shí)現(xiàn)原子操作。
對(duì)于基本的內(nèi)存操作的原子性處理器會(huì)自動(dòng)保證,否則并發(fā)的概念就將不復(fù)存在了。處理器保證從內(nèi)存中讀取或者寫入一個(gè)字節(jié)是原子的,意思是當(dāng)一個(gè)處理器讀取一個(gè)字節(jié)時(shí),其他處理器不能訪問這個(gè)字節(jié)的內(nèi)存地址。但是復(fù)雜內(nèi)存操作的原子性需要借助總線鎖定和緩存鎖定兩個(gè)機(jī)制來保證。
3.1 使用總線鎖保證復(fù)雜操作原子性
所謂總線鎖就是使用處理器提供的一個(gè)LOCK#信號(hào),當(dāng)一個(gè)處理器在總線上輸出此信號(hào)時(shí),其他處理器的請(qǐng)求將被阻塞,那么該處理器就可以獨(dú)占共享內(nèi)存(聽到鎖是不是很親切,很熟悉)。感覺和處理器自動(dòng)保證基本內(nèi)存操作原子性的原理差不多,都是排斥其他處理器同時(shí)操作,只不過前者獨(dú)占的是某個(gè)字節(jié)的內(nèi)存地址,而總線鎖獨(dú)占的是整個(gè)內(nèi)存。
獨(dú)占整個(gè)內(nèi)存聽著就很浪費(fèi),沒有代價(jià)小點(diǎn)兒的方法嗎?當(dāng)然有,緩存鎖定鎖定機(jī)制就是。
3.2 使用緩存鎖定來保證原子性
在上面高速緩存的知識(shí)里面,我們知道每個(gè)處理器都有一套高速緩存用于緩存頻繁操作的內(nèi)存,處理器不直接操作主內(nèi)存的地址,而是操作這些緩存,操作完成之后再將緩存數(shù)據(jù)寫回主內(nèi)存。在這種模式下,只要保證緩存寫回的準(zhǔn)確就可以保證該操作的原子性。這也就是緩存鎖定保證復(fù)雜操作的原子性的原理。下面是規(guī)范的描述:
內(nèi)存區(qū)域如果被緩存在處理的緩存行中,并且在Lock操作期間被鎖定,那么當(dāng)它執(zhí)行鎖操作回寫到內(nèi)存時(shí),處理器不在總線上聲言LOCK#信號(hào),而是修改內(nèi)部的內(nèi)存地址,并允許它的緩存一致性機(jī)制來保證操作的原子性,因?yàn)榫彺嬉恢滦詸C(jī)制會(huì)阻止同時(shí)修改由兩個(gè)以上處理器緩存的內(nèi)存區(qū)域數(shù)據(jù),當(dāng)其他處理器回寫已經(jīng)被鎖定的緩存行數(shù)據(jù)時(shí),會(huì)使自己的緩存行無效。
現(xiàn)又有一個(gè)問題了,既然有低損耗緩存鎖定機(jī)制,為什么還要用總線鎖定機(jī)制?這是因?yàn)橛幸韵聝煞N情況不能使用緩存鎖定:
第一種情況是:當(dāng)操作的數(shù)據(jù)不能被緩存在處理器內(nèi)部,或者操作的數(shù)據(jù)跨越了多個(gè)緩存行時(shí)。
第二種情況是:有些處理器不支持緩存鎖定,比如Intel 486 和Pentium 處理器。
上面這些計(jì)算機(jī)硬件知識(shí)都是和并發(fā)相關(guān)的,因?yàn)镴ava程序也是在計(jì)算機(jī)上運(yùn)行的,那么Java并發(fā)應(yīng)該也是基于計(jì)算機(jī)的并發(fā)特點(diǎn)做的設(shè)計(jì),了解了這些知識(shí),后面可以比較容易的理解Java并發(fā)的知識(shí)。
參考文獻(xiàn) 《Java并發(fā)編程的藝術(shù)》
總結(jié)
以上是生活随笔為你收集整理的java学生背景知识要求,好好学习Java并发 一、背景知识的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kmp算法详解php,php中字符串匹配
- 下一篇: matlab矩阵对某一列求和,将矩阵中的