最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

聊聊Java和CPU的關(guān)系

 更新時(shí)間:2016年08月31日 11:07:48   作者:放飛夢(mèng)想  
java和cpu關(guān)系不大,但是也有點(diǎn)關(guān)系,下面我們來(lái)聊一聊java和cpu的關(guān)系,感興趣的朋友一起看看吧

其實(shí)寫(xiě)Java的人貌似和CPU沒(méi)啥關(guān)系,最多最多和我們?cè)谇懊嫣峒暗降娜绾螌PU跑滿(mǎn)、如何設(shè)置線程數(shù)有點(diǎn)關(guān)系,但是那個(gè)算法只是一個(gè)參考,很多場(chǎng)景不同需要采取實(shí)際的手段來(lái)解決才可以;而且將CPU跑滿(mǎn)后我們還會(huì)考慮如何讓CPU不是那么滿(mǎn),呵呵,人類(lèi),就是這么XX,呵呵,好了,本文要說(shuō)的是其他的一些東西,也許你在java的寫(xiě)代碼時(shí)幾乎不用關(guān)注CPU,因?yàn)闈M(mǎn)足業(yè)務(wù)才是第一重要的事情,如果你要做到框架級(jí)別,為框架提供很多共享數(shù)據(jù)緩存之類(lèi)的東西,中間必然存在很多數(shù)據(jù)的征用問(wèn)題,當(dāng)然java提供了很多concurrent包的類(lèi),你可以用它,但是它內(nèi)部如何做的,你要明白細(xì)節(jié)才能用得比較好,否則還不如不用,本文可能不是闡述這些內(nèi)容作為重點(diǎn),因?yàn)槿鐦?biāo)題黨:我們要說(shuō)CPU,呵呵。

還是那句話,貌似java和CPU沒(méi)有多少關(guān)系,我們現(xiàn)在來(lái)聊聊有啥關(guān)系;

1、當(dāng)遇到共享元素,我們通常第一想法是通過(guò)volatile來(lái)保證一致性讀的操作,也就是絕對(duì)的可見(jiàn)性,所謂可見(jiàn)性,就是每次要使用該數(shù)據(jù)的時(shí)候,CPU不會(huì)使用任何cache的內(nèi)容都會(huì)從內(nèi)存中去抓取一次數(shù)據(jù),并且這個(gè)過(guò)程對(duì)多CPU仍然有效,也就是相當(dāng)CPU和內(nèi)存之間此時(shí)是同步的,CPU會(huì)像總線發(fā)出一個(gè)Lock addl 0類(lèi)似的的匯編指令,+0但相對(duì)于什么都不會(huì)做;不過(guò)一旦該指令完成,后續(xù)操作將不再影響這個(gè)元素其他線程的訪問(wèn),也就是他能實(shí)現(xiàn)的絕對(duì)可見(jiàn)性,但是不能實(shí)現(xiàn)一致性操作,也就是說(shuō),volatile不能實(shí)現(xiàn)的是i++這類(lèi)操作的一致性(在多線程下并發(fā)),因?yàn)閕++操作是被分解為:

int tmp = i;
tmp = tmp + 1;
i = tmp;

這三個(gè)步驟來(lái)完成,從這點(diǎn)你也能看出i++為什么能實(shí)現(xiàn)先做其他的事情再自我加1,因?yàn)樗v值賦予給了另一個(gè)變量。

2、我們要用到多線程并發(fā)一致性,就需要用到鎖的機(jī)制,目前類(lèi)似Atomic*的東西基本可以滿(mǎn)足這些要求,內(nèi)部提供了很多unsafe類(lèi)的方法,通過(guò)不斷對(duì)比絕對(duì)可見(jiàn)性的數(shù)據(jù)來(lái)保證獲取的數(shù)據(jù)是最新的;接下來(lái)我們繼續(xù)來(lái)說(shuō)一些CPU其他的事情。

3、以前我們?yōu)榱藢PU跑滿(mǎn),但是無(wú)論如何跑不滿(mǎn),因?yàn)槲覀冮_(kāi)始說(shuō)了忽略掉內(nèi)存與CPU的延遲,今天既然提及到這兒,我們就簡(jiǎn)單說(shuō)下延遲,一般來(lái)講現(xiàn)在的CPU有三級(jí)cache,年代不同延遲不同,所以具體數(shù)字只能說(shuō)個(gè)大概而已,現(xiàn)在的CPU一般一級(jí)cache的延遲在1-2ns,二級(jí)cache一般是幾個(gè)ns到十來(lái)ns左右,三級(jí)cache一般是30ns到50ns不等,內(nèi)存訪問(wèn)普遍會(huì)上到70ns甚至更多(計(jì)算機(jī)發(fā)展速度很快,這個(gè)值也僅僅在某些CPU上的數(shù)據(jù),做一個(gè)范圍參考而已);別看這個(gè)延遲很小,都是納秒級(jí)別,你會(huì)發(fā)現(xiàn)你的程序被拆分為指令運(yùn)算的時(shí)候,會(huì)有很多CPU交互,每次交互的延遲如果有這么大的偏差,此時(shí)系統(tǒng)性能是會(huì)有變化的;

4、回到剛才說(shuō)的volatile,它每次從內(nèi)存中獲取數(shù)據(jù),就是放棄cache,自然如果在某些單線程的操作中,會(huì)變得更加慢,有些時(shí)候我們也不得不這樣做,甚至于讀寫(xiě)操作都要求一致性,甚至于整個(gè)數(shù)據(jù)塊都被同步,我們只能在一定程度上降低鎖的粒度,但是不能完全沒(méi)有鎖,即使是CPU本身級(jí)別也會(huì)有指令級(jí)別的限制。

5、在CPU本身級(jí)別的原子操作一般叫屏障,有讀屏障、寫(xiě)屏障等,一般是基于一個(gè)點(diǎn)的觸發(fā),當(dāng)程序多條指令發(fā)送到CPU的時(shí)候,有些指令未必是按照程序的順序來(lái)執(zhí)行,有些必須按照程序的順序來(lái)執(zhí)行,只要能最終保證一致即可;在排序上,JIT在運(yùn)行時(shí)會(huì)做改變,CPU指令級(jí)別也會(huì)做改變,原因主要是為了優(yōu)化運(yùn)行時(shí)指令讓程序跑得更快。

6、CPU級(jí)別會(huì)對(duì)內(nèi)存做cache line的操作,所謂cache line會(huì)連續(xù)讀一塊內(nèi)存,一般和CPU型號(hào)和架構(gòu)有關(guān)系,現(xiàn)在很多CPU每次讀取連續(xù)內(nèi)存一般是64byte,早期的有32byte的,所以在某些數(shù)組遍歷的時(shí)候會(huì)比較快(基于列遍歷很慢),但這個(gè)并不完全對(duì),下面會(huì)對(duì)照一些相反的情況來(lái)說(shuō)。

7、CPU對(duì)數(shù)據(jù)如果發(fā)生了修改,此時(shí)就不得不說(shuō)CPU對(duì)數(shù)據(jù)修改的狀態(tài),數(shù)據(jù)如果都被讀取,在多CPU下可以被多線程并行讀取并,當(dāng)對(duì)數(shù)據(jù)塊發(fā)生寫(xiě)操作的時(shí)候,就不一樣了,數(shù)據(jù)塊會(huì)有獨(dú)占、修改、失效等狀態(tài),數(shù)據(jù)修改后自然就會(huì)失效,當(dāng)在多CPU下,多個(gè)線程都在對(duì)同一個(gè)數(shù)據(jù)塊進(jìn)行修改時(shí),就會(huì)發(fā)生CPU之間的總線數(shù)據(jù)拷貝(QPI),當(dāng)然如果修改到同一個(gè)數(shù)據(jù)上的時(shí)候我們是沒(méi)有辦法的,但是回到第6點(diǎn)的cache line里面,問(wèn)題就比較麻煩了,如果數(shù)據(jù)是在同一個(gè)數(shù)組上,而數(shù)組中的元素會(huì)被同時(shí)cache line到一個(gè)CPU上的時(shí)候,多線程的QPI就會(huì)非常頻繁,有些時(shí)候即使是數(shù)組上組裝的是對(duì)象也會(huì)出現(xiàn)這個(gè)問(wèn)題,如:

class InputInteger {
private int value;
public InputInteger(int i) {
this.value = i;
}
}
InputInteger[] integers = new InputInteger[SIZE];
for(int i=0 ; i < SIZE ; i++) {
integers[i] = new InputInteger(i);
}

此時(shí)你看出來(lái)integers里面放的全部是對(duì)象,數(shù)組上只有對(duì)象的引用,但是對(duì)象的排布理論上說(shuō)各自對(duì)象是獨(dú)立的,不會(huì)連續(xù)存放,不過(guò)java在分配對(duì)象內(nèi)存的時(shí)候,很多時(shí)候,在Eden區(qū)域是連續(xù)分配的,當(dāng)在for循環(huán)的時(shí)候,如果沒(méi)有其他線程的接入,這些對(duì)象就會(huì)被存放在一起,即使被GC到OLD區(qū)域也很有可能會(huì)放在一起,所以靠簡(jiǎn)單對(duì)象來(lái)解決cache line后還對(duì)整個(gè)數(shù)組修改的方式貌似不靠譜,因?yàn)閕nt 是4字節(jié),如果在64模式下,這個(gè)大小是24字節(jié)(有4byte補(bǔ)齊),指針壓縮開(kāi)啟是16byte;也就是每次cpu可以看齊3-4個(gè)對(duì)象,如何讓CPUcache了,但是又不影響系統(tǒng)的QPI,別想通過(guò)分隔對(duì)象來(lái)完成,因?yàn)镚C過(guò)程內(nèi)存拷貝過(guò)程很可能會(huì)拷貝到一起,最好的辦法是補(bǔ)齊,雖然有點(diǎn)浪費(fèi)內(nèi)存,但是這是最靠譜的方法,就是將對(duì)象補(bǔ)齊到64字節(jié),上述若未開(kāi)啟指針壓縮有24byte,此時(shí)還有40個(gè)字節(jié),只需要在對(duì)象內(nèi)部增加5個(gè)long即可。

class InputInteger {
public int value;
private long a1,a2,a3,a4,a5;
}

呵呵,這個(gè)辦法很土,不過(guò)很管用,有些時(shí)候,Jvm編譯的時(shí)候發(fā)現(xiàn)這幾個(gè)參數(shù)啥都沒(méi)做,就直接給你干掉了,優(yōu)化無(wú)效,土辦法加土辦法就是在一個(gè)方法體里面簡(jiǎn)單對(duì)這5個(gè)參數(shù)做一個(gè)操作(都用上),但是這個(gè)方法永遠(yuǎn)不調(diào)用它即可。

8、在CPU這個(gè)級(jí)別有些時(shí)候就未必能先做盡量先做的道理為王者了,類(lèi)似獲取鎖這種操作,在AtomicIntegerFieldUpdater的操作,如果調(diào)用getAndSet(true)在單線程下你會(huì)發(fā)現(xiàn)跑得還蠻快,在多核CPU下就開(kāi)始變慢,為什么上面說(shuō)得很清楚了,因?yàn)間etAndSet里面是修改后對(duì)比,先改了再說(shuō),QPI會(huì)很高,所以這個(gè)時(shí)候,先做get操作,再修改才是比較好的做法;還有就是獲取一次,如果獲取不到,就讓步一下,讓其他的線程去做其他的事情;

9、CPU有些時(shí)候?yàn)榱私鉀Q某些CPU忙和不繁忙的問(wèn)題,會(huì)有很多算法來(lái)解決,如NUMA是其中一種方案,不過(guò)不論哪種架構(gòu)都在一定場(chǎng)景下比較有用,對(duì)有所有場(chǎng)景未必有效;有隊(duì)列鎖機(jī)制來(lái)完成對(duì)CPU狀態(tài)管理,不過(guò)這又存在了cache line的問(wèn)題,因?yàn)闋顟B(tài)都是經(jīng)常改變的,各類(lèi)應(yīng)用程序的內(nèi)核為了配合CPU也會(huì)出一些算法來(lái)做,使得CPU可以更加有效的利用起來(lái),如CLH隊(duì)列等。

有關(guān)這方面的細(xì)節(jié)會(huì)很多如用普通變量循環(huán)疊加和用volatile類(lèi)型的做以及Atomic*系列的來(lái)做,完全是不一樣的;多維度數(shù)組循環(huán),按照不同緯度向后次序來(lái)循環(huán)也是不一樣的,細(xì)節(jié)上點(diǎn)很多,明白為什么就在實(shí)際優(yōu)化過(guò)程中有靈感了;鎖的細(xì)節(jié)說(shuō)太細(xì)很暈,在系統(tǒng)底層的級(jí)別,始終有一些輕量級(jí)的原子操作,不論誰(shuí)說(shuō)他的代碼是不需要加鎖的,最細(xì)的可以細(xì)到CPU在每個(gè)瞬間只能執(zhí)行一條指令那么簡(jiǎn)單,多核心CPU在總線級(jí)別也會(huì)有共享區(qū)來(lái)控制一些內(nèi)容,有讀級(jí)別、寫(xiě)級(jí)別、內(nèi)存級(jí)別等,在不同的場(chǎng)景下使得鎖的粒度盡量降低,那么系統(tǒng)的性能不言而喻,很正常的結(jié)果。

相關(guān)文章

  • Java中RabbitMQ消息隊(duì)列的交換機(jī)詳解

    Java中RabbitMQ消息隊(duì)列的交換機(jī)詳解

    這篇文章主要介紹了Java中的RabbitMQ交換機(jī)詳解,消息隊(duì)列是指利用高效可靠的消息傳遞機(jī)制進(jìn)行與平臺(tái)無(wú)關(guān)的數(shù)據(jù)交流,并基于數(shù)據(jù)通信來(lái)進(jìn)行分布式系統(tǒng)的集成,是在消息的傳輸過(guò)程中保存消息的容器,需要的朋友可以參考下
    2023-07-07
  • Idea springboot如何實(shí)現(xiàn)批量啟動(dòng)微服務(wù)

    Idea springboot如何實(shí)現(xiàn)批量啟動(dòng)微服務(wù)

    這篇文章主要介紹了Idea springboot如何實(shí)現(xiàn)批量啟動(dòng)微服務(wù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 詳解Java字節(jié)碼編程之非常好用的javassist

    詳解Java字節(jié)碼編程之非常好用的javassist

    這篇文章主要介紹了詳解Java字節(jié)碼編程之非常好用的javassist,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Java DecimalFormat 保留小數(shù)位及四舍五入的陷阱介紹

    Java DecimalFormat 保留小數(shù)位及四舍五入的陷阱介紹

    這篇文章主要介紹了Java DecimalFormat 保留小數(shù)位及四舍五入的陷阱,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 淺談java實(shí)現(xiàn)redis的發(fā)布訂閱(簡(jiǎn)單易懂)

    淺談java實(shí)現(xiàn)redis的發(fā)布訂閱(簡(jiǎn)單易懂)

    本篇文章主要介紹了淺談java實(shí)現(xiàn) redis的發(fā)布訂閱(簡(jiǎn)單易懂),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • 一文詳解SpringBoot如何優(yōu)雅地實(shí)現(xiàn)異步調(diào)用

    一文詳解SpringBoot如何優(yōu)雅地實(shí)現(xiàn)異步調(diào)用

    SpringBoot想必大家都用過(guò),但是大家平時(shí)使用發(fā)布的接口大都是同步的,那么你知道如何優(yōu)雅的實(shí)現(xiàn)異步呢?這篇文章就來(lái)和大家詳細(xì)聊聊
    2023-03-03
  • Java的云打印Lodop

    Java的云打印Lodop

    這篇文章主要介紹了Java的云打印Lodop 的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • Java面試題沖刺第二十二天-- Nginx

    Java面試題沖刺第二十二天-- Nginx

    這篇文章主要為大家分享了最有價(jià)值的三道關(guān)于Nginx的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Spring注解之@validated使用詳解

    Spring注解之@validated使用詳解

    spring-boot中可以用@validated來(lái)校驗(yàn)數(shù)據(jù),如果數(shù)據(jù)異常則會(huì)統(tǒng)一拋出異常,方便異常中心統(tǒng)一處理,這篇文章主要介紹了Spring注解之@validated使用,需要的朋友可以參考下
    2023-01-01
  • Java分頁(yè)查詢(xún)--分頁(yè)顯示(實(shí)例講解)

    Java分頁(yè)查詢(xún)--分頁(yè)顯示(實(shí)例講解)

    下面小編就為大家?guī)?lái)一篇Java分頁(yè)查詢(xún)--分頁(yè)顯示(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08

最新評(píng)論

兴业县| 桑日县| 诏安县| 荆门市| 郯城县| 荣昌县| 南和县| 田阳县| 巨鹿县| 乳山市| 大理市| 错那县| 彭阳县| 白朗县| 凯里市| 扎兰屯市| 永丰县| 阿巴嘎旗| 镶黄旗| 永泰县| 青铜峡市| 山东省| 白水县| 武冈市| 延川县| 岗巴县| 小金县| 赤水市| 贡觉县| 邳州市| 灵宝市| 关岭| 绥棱县| 常山县| 昌吉市| 巴彦淖尔市| 临朐县| 沙田区| 融水| 濮阳县| 庆云县|