摘要:測(cè)試吞吐量的時(shí)候,是通過每一種實(shí)現(xiàn)都重復(fù)測(cè)試超過次,每一次都運(yùn)行秒以上,以保證系統(tǒng)足夠預(yù)熱,下面的結(jié)果都是第次之后平均每秒吞吐量。以我的經(jīng)驗(yàn)看,教學(xué)和開發(fā)中的無鎖算法,不僅能顯著改善吞吐量同時(shí)他們也提供更低的延遲。
上周在由Heinz Kabutz通過JCrete?組織的開放空間會(huì)議(unconference)上,我參加一個(gè)新的java規(guī)范 JSR166?StampedLock 的審查會(huì)議。 StampedLock 是為了解決多個(gè)readers?并發(fā)訪問共享狀態(tài)時(shí),系統(tǒng)出現(xiàn)的內(nèi)存地址競(jìng)爭(zhēng)問題。在設(shè)計(jì)上通過使用樂觀的讀操作, StampedLock
比 ReentrantReadWriteLock 更加高效;
在會(huì)議期間,我突然意思到兩點(diǎn):
我想是時(shí)候該去回顧java中鎖的實(shí)現(xiàn)的現(xiàn)狀。
雖然StampedLock 看上去是JDK很好的補(bǔ)充,但是似乎忽略了一個(gè)事實(shí),即在多個(gè)reader的場(chǎng)景里,無鎖的算法通常是更好的解決方案。
測(cè)試為了比較不同的實(shí)現(xiàn)方式,我需要采用一種不偏向任意一方的API測(cè)試用例。 比如:API必須不產(chǎn)生垃圾、并且允許方法是原子性的。一個(gè)簡(jiǎn)單的測(cè)試用例是設(shè)計(jì)一個(gè)可在兩維空間中移動(dòng)其位置的太空船,它位置的坐標(biāo)可以原子性的讀?。幻恳淮问挛锢镏辽傩枰x寫2個(gè)域,這使得并發(fā)變得非常有趣;
/** * 并發(fā)接口,表示太空船可以在2維的空間中移動(dòng)位置;并且同時(shí)更新讀取位置 */ public interface Spaceship { /** * 讀取太空船的位置到參數(shù)數(shù)組 coordinates 中 * * @param coordinates 保存讀取到的XY坐標(biāo). * @return 當(dāng)前的狀態(tài) */ int readPosition(final int[] coordinates); /** * 通過增加XY的值表示移動(dòng)太空船的位置。 * * @param xDelta x坐標(biāo)軸上移動(dòng)的增量. * @param yDelta y坐標(biāo)軸上移動(dòng)的增量. * @return the number of attempts made to write the new coordinates. */ int move(final int xDelta, final int yDelta); }
上面的API通過分解一個(gè)不變的位置對(duì)象,本身是干凈的。但是我想保證它不產(chǎn)生垃圾,并且需要能最直接的更新多個(gè)內(nèi)容域。這個(gè)API可以很容易地?cái)U(kuò)展到三維空間,并實(shí)現(xiàn)原子性要求。
為每一個(gè)飛船都設(shè)置多個(gè)實(shí)現(xiàn),并且作為一個(gè)測(cè)試套件。本文中所有的代碼和結(jié)果都可以在這里找到。
該測(cè)試套件會(huì)依次運(yùn)行每一種實(shí)現(xiàn).并且使用?megamorphic dispatch模式,防止并發(fā)訪問中的方法內(nèi)聯(lián)(inlining),鎖粗化(lock-coarsening),循環(huán)展開(loop unrolling)的問題;
每種實(shí)現(xiàn)都執(zhí)行下面4個(gè)不同的線程的情況,結(jié)果也是不同的;
1 reader – 1 writer 2 readers – 1 writer 3 readers – 1 writer 2 readers – 2 writers
所有的測(cè)試運(yùn)行在64位機(jī)器、Java版本:1.7.0_25、 Linux版本:3.6.30、4核 2.2GHz Ivy Bridge (第三代Core i系列處理器)i7-3632QM的環(huán)境上。
測(cè)試吞吐量的時(shí)候,是通過每一種實(shí)現(xiàn)都重復(fù)測(cè)試超過5次,每一次都運(yùn)行5秒以上,以保證系統(tǒng)足夠預(yù)熱,下面的結(jié)果都是第5次之后平均每秒吞吐量。為了更像一個(gè)典型的java應(yīng)用;沒有采用會(huì)導(dǎo)致明顯減少差異的線程依附性(thread affinity)和多核隔離(core isolation?)技術(shù);
結(jié)果上述圖表的原始數(shù)據(jù)可以在這里找到
分析結(jié)果里面真正令我吃驚的是ReentrantReadWriteLock的性能,我沒有想到的是,在這樣的場(chǎng)景下它在讀和少量寫之間取得的巨大的平衡性,
我主要的收獲:
StampedLock 對(duì)現(xiàn)存的鎖實(shí)現(xiàn)有巨大的改進(jìn),特別是在讀線程越來越多的場(chǎng)景下:
StampedLock有一個(gè)復(fù)雜的API,對(duì)于加鎖操作,很容易誤用其他方法;
當(dāng)只有2個(gè)競(jìng)爭(zhēng)者的時(shí)候,Synchronised是一個(gè)很好的通用的鎖實(shí)現(xiàn);
當(dāng)線程增長(zhǎng)能夠預(yù)估,ReentrantLock是一個(gè)很好的通用的鎖實(shí)現(xiàn);
選擇使用ReentrantReadWriteLock時(shí),必須經(jīng)過小心的適度的測(cè)試;所有重大的決定,必須在基于測(cè)試數(shù)據(jù)的基礎(chǔ)上做決定;
無鎖的實(shí)現(xiàn)比基于鎖的算法有更好短吞吐量;
結(jié)論:非常開心能看到無鎖技術(shù)對(duì)基于鎖的算法的影響; 樂觀鎖的策略,實(shí)際上就是一個(gè)無鎖算法技術(shù)。
以我的經(jīng)驗(yàn)看,教學(xué)和開發(fā)中的無鎖算法,不僅能顯著改善吞吐量;同時(shí)他們也提供更低的延遲。
原文 Lock based vs lock free concurrent
翻譯 曹姚君?校對(duì) 方騰飛
via ifeve
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64054.html
摘要:在本例中,講述的無鎖來自于并發(fā)包我們將這個(gè)無鎖的稱為。在這里,我們使用二維數(shù)組來表示的內(nèi)部存儲(chǔ),如下變量存放所有的內(nèi)部元素。為什么使用二維數(shù)組去實(shí)現(xiàn)一個(gè)一維的呢這是為了將來進(jìn)行動(dòng)態(tài)擴(kuò)展時(shí)可以更加方便。 我們已經(jīng)比較完整得介紹了有關(guān)無鎖的概念和使用方法。相對(duì)于有鎖的方法,使用無鎖的方式編程更加考驗(yàn)一個(gè)程序員的耐心和智力。但是,無鎖帶來的好處也是顯而易見的,第一,在高并發(fā)的情況下,它比有鎖...
摘要:因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。減少線程的使用。舉個(gè)例子如果說服務(wù)器的帶寬只有,某個(gè)資源的下載速度是,系統(tǒng)啟動(dòng)個(gè)線程下載該資源并不會(huì)導(dǎo)致下載速度編程,所以在并發(fā)編程時(shí),需要考慮這些資源的限制。 最近私下做一項(xiàng)目,一bug幾日未解決,總惶恐。一日頓悟,bug不可怕,怕的是項(xiàng)目不存在bug,與其懼怕,何不與其剛正面。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Jav...
摘要:相比與其他操作系統(tǒng)包括其他類系統(tǒng)有很多的優(yōu)點(diǎn),其中有一項(xiàng)就是,其上下文切換和模式切換的時(shí)間消耗非常少。因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。減少線程的使用。很多編程語言中都有協(xié)程。所以如何避免死鎖的產(chǎn)生,在我們使用并發(fā)編程時(shí)至關(guān)重要。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)syn...
摘要:本文旨在對(duì)鎖相關(guān)源碼本文中的源碼來自使用場(chǎng)景進(jìn)行舉例,為讀者介紹主流鎖的知識(shí)點(diǎn),以及不同的鎖的適用場(chǎng)景。中,關(guān)鍵字和的實(shí)現(xiàn)類都是悲觀鎖。自適應(yīng)意味著自旋的時(shí)間次數(shù)不再固定,而是由前一次在同一個(gè)鎖上的自旋時(shí)間及鎖的擁有者的狀態(tài)來決定。 前言 Java提供了種類豐富的鎖,每種鎖因其特性的不同,在適當(dāng)?shù)膱?chǎng)景下能夠展現(xiàn)出非常高的效率。本文旨在對(duì)鎖相關(guān)源碼(本文中的源碼來自JDK 8)、使用場(chǎng)景...
閱讀 1424·2021-11-22 09:34
閱讀 1386·2021-09-22 14:57
閱讀 3418·2021-09-10 10:50
閱讀 1408·2019-08-30 15:54
閱讀 3700·2019-08-29 17:02
閱讀 3483·2019-08-29 12:54
閱讀 2622·2019-08-27 10:57
閱讀 3328·2019-08-26 12:24