摘要:因此將變量存放于獨(dú)立的緩存行中,也有助于變量在多線程訪問(wèn)是的性能提升實(shí)戰(zhàn)高并發(fā)程序設(shè)計(jì),大量的高并發(fā)庫(kù)都會(huì)采用這種技術(shù)。
在Java程序中,多線程幾乎已經(jīng)無(wú)處不在。與單線程相比,多線程程序的設(shè)計(jì)和實(shí)現(xiàn)略微困難,但通過(guò)多線程,我們卻可以獲得多核CPU帶來(lái)的性能飛躍,從這個(gè)角度說(shuō),多線程是一種值得嘗試的技術(shù)。那么如何寫出高效的多線程程序呢?
有關(guān)多線程的誤區(qū):線程越多,性能越好
不少初學(xué)者可能認(rèn)為,線程數(shù)量越多,那么性能應(yīng)該越好。因?yàn)槌绦蚪o我們的直觀感受總是這樣。一個(gè)兩個(gè)線程可能跑的很難,線程一多可能就快了。但事實(shí)并非如此。因?yàn)橐粋€(gè)物理CPU一次只能執(zhí)行一個(gè)線程,多個(gè)線程則意味著必須進(jìn)行線程的上下文切換,而這個(gè)代價(jià)是很高的。因此,線程數(shù)量必須適量,最好的情況應(yīng)該是N個(gè)CPU使用N個(gè)線程,并且讓每個(gè)CPU的占有率都達(dá)到100%,這種情況下,系統(tǒng)的吞吐量才發(fā)揮到極致。但現(xiàn)實(shí)中,不太可能讓單線程獨(dú)占CPU達(dá)到100%,一個(gè)普遍的愿意是因?yàn)镮O操作,無(wú)論是磁盤IO還是網(wǎng)絡(luò)IO都是很慢的。線程在執(zhí)行中會(huì)等待,因此效率就下來(lái)了。這也就是為什么在一個(gè)物理核上執(zhí)行多個(gè)線程會(huì)感覺效率高了,對(duì)于程序調(diào)度來(lái)說(shuō),一個(gè)線程等待時(shí),也正是其它線程執(zhí)行的大好機(jī)會(huì),因此,CPU資源得到了充分的利用。
盡可能不要掛起線程
多線程程序免不了要同步,最直接的方法就是使用鎖。每次只允許一個(gè)線程進(jìn)入臨界區(qū),讓其它相關(guān)線程等待。等待有2種,一種是直接使用操作系統(tǒng)指令掛起線程,另外一種是自旋等待。在操作系統(tǒng)直接掛起,是一種簡(jiǎn)單粗暴的實(shí)現(xiàn),性能較差,不太適用于高并發(fā)的場(chǎng)景,因?yàn)殡S之而來(lái)的問(wèn)題就是大量的線程上下文切換。如果可以,嘗試一下進(jìn)行有限的自旋等待,等待不成功再去掛起線程也不遲。這樣很有可能可以避免一些無(wú)謂的開銷。JDK中ConcurrentHashMap的實(shí)現(xiàn)里就有一些自旋等待的實(shí)現(xiàn)。此外Java虛擬機(jī)層面,對(duì)synchronized關(guān)鍵字也有自旋等待的優(yōu)化。
善用“無(wú)鎖”
阻塞線程會(huì)帶來(lái)性能開銷,因此,一種提供性能的方案就是使用無(wú)鎖的CAS操作。JDK中的原子類,如AtomicInteger正是使用了這種方案。在高并發(fā)環(huán)境中,沖突較多的情況下,它們的性能遠(yuǎn)遠(yuǎn)好于傳統(tǒng)的鎖操作(《實(shí)戰(zhàn)Java高并發(fā)程序設(shè)計(jì)》 P158)。
處理好“偽共享”問(wèn)題
大家知道,CPU有一個(gè)高速緩存Cache。在Cache中,讀寫數(shù)據(jù)的最小單位是緩存行,如果2個(gè)變量存在一個(gè)緩存行中,那么在多線程訪問(wèn)中,可能會(huì)相互影響彼此的性能。因此將變量存放于獨(dú)立的緩存行中,也有助于變量在多線程訪問(wèn)是的性能提升(《實(shí)戰(zhàn)Java高并發(fā)程序設(shè)計(jì)》 P200),大量的高并發(fā)庫(kù)都會(huì)采用這種技術(shù)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/65379.html
摘要:阿姆達(dá)爾定律定律是計(jì)算機(jī)科學(xué)中非常重要的定律。它定義了串行系統(tǒng)并行化后的加速比的計(jì)算公式和理論上線。需要從根本上修改程序的串行行為,提高系統(tǒng)內(nèi)可并行化的模塊比重,在此基礎(chǔ)上,合理增加并行處理器數(shù)量,才能以最小的投入,得到最大的加速比。 有關(guān)為什么要使用并行程序的問(wèn)題前面已經(jīng)進(jìn)行了簡(jiǎn)單的探討。總的來(lái)說(shuō),最重要的應(yīng)該是處于兩個(gè)目的。 第一,為了獲得更好的性能; 第二,由于業(yè)務(wù)模型的需要,確...
摘要:系統(tǒng)級(jí)線程核心級(jí)線程由操作系統(tǒng)內(nèi)核進(jìn)行管理。值得注意的是多線程的存在,不是提高程序的執(zhí)行速度。實(shí)現(xiàn)多線程上面說(shuō)了一大堆基礎(chǔ),理解完的話。虛擬機(jī)的啟動(dòng)是單線程的還是多線程的是多線程的。 前言 之前花了一個(gè)星期回顧了Java集合: Collection總覽 List集合就這么簡(jiǎn)單【源碼剖析】 Map集合、散列表、紅黑樹介紹 HashMap就是這么簡(jiǎn)單【源碼剖析】 LinkedHashMa...
摘要:前言談到并行,我們可能最先想到的是線程,多個(gè)線程一起運(yùn)行,來(lái)提高我們系統(tǒng)的整體處理速度為什么使用多個(gè)線程就能提高處理速度,因?yàn)楝F(xiàn)在計(jì)算機(jī)普遍都是多核處理器,我們需要充分利用資源如果站的更高一點(diǎn)來(lái)看,我們每臺(tái)機(jī)器都可以是一個(gè)處理節(jié)點(diǎn),多臺(tái)機(jī)器 前言 談到并行,我們可能最先想到的是線程,多個(gè)線程一起運(yùn)行,來(lái)提高我們系統(tǒng)的整體處理速度;為什么使用多個(gè)線程就能提高處理速度,因?yàn)楝F(xiàn)在計(jì)算機(jī)普遍都...
摘要:虛擬機(jī)所處的區(qū)域,則表示它是屬于新生代收集器還是老年代收集器。虛擬機(jī)總共運(yùn)行了分鐘,其中垃圾收集花掉分鐘,那么吞吐量就是。收集器線程所占用的數(shù)量為。 本文主要從GC(垃圾回收)的角度試著對(duì)jvm中的內(nèi)存分配策略與相應(yīng)的垃圾收集器做一個(gè)介紹。 注:還是老規(guī)矩,本著能畫圖就不BB原則,盡量將各知識(shí)點(diǎn)通過(guò)思維導(dǎo)圖或者其他模型圖的方式進(jìn)行說(shuō)明。文字僅記錄額外的思考與心得,以及其他特殊情況 內(nèi)存...
摘要:串行與并行可以分為串行與并行兩種,串行流和并行流差別就是單線程和多線程的執(zhí)行。返回串行流返回并行流和方法返回的都是類型的對(duì)象,說(shuō)明它們?cè)诠δ艿氖褂蒙鲜菦]差別的。唯一的差別就是單線程和多線程的執(zhí)行。 Stream是什么 Stream是Java8中新加入的api,更準(zhǔn)確的說(shuō): Java 8 中的 Stream 是對(duì)集合(Collection)對(duì)象功能的增強(qiáng),它專注于對(duì)集合對(duì)象進(jìn)行各種非常便...
閱讀 836·2021-09-07 09:58
閱讀 2693·2021-08-31 09:42
閱讀 2867·2019-08-30 14:18
閱讀 3094·2019-08-30 14:08
閱讀 1840·2019-08-30 12:57
閱讀 2765·2019-08-26 13:31
閱讀 1306·2019-08-26 11:58
閱讀 1060·2019-08-23 18:06