麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

java AtomicInteger 源碼之CAS

2019-11-14 09:23:16
字體:
供稿:網(wǎng)友

樂觀鎖與悲觀鎖

當(dāng)一個(gè)線程被掛起時(shí),加入到阻塞隊(duì)列,在一定的時(shí)間或條件下,在通過notify(),notifyAll()喚醒回來。在某個(gè)資源不可用的時(shí)候,就將cpu讓出,把當(dāng)前等待線程切換為阻塞狀態(tài)。等到資源(比如一個(gè)共享數(shù)據(jù))可用了,那么就將線程喚醒,讓他進(jìn)入runnable狀態(tài)等待cpu調(diào)度。這就是典型的悲觀鎖的實(shí)現(xiàn)。獨(dú)占鎖是一種悲觀鎖,synchronized就是一種獨(dú)占鎖,它假設(shè)最壞的情況,并且只有在確保其它線程不會(huì)造成干擾的情況下執(zhí)行,會(huì)導(dǎo)致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖。

  但是,由于在進(jìn)程掛起和恢復(fù)執(zhí)行過程中存在著很大的開銷。當(dāng)一個(gè)線程正在等待鎖時(shí),它不能做任何事,所以悲觀鎖有很大的缺點(diǎn)。舉個(gè)例子,如果一個(gè)線程需要某個(gè)資源,但是這個(gè)資源的占用時(shí)間很短,當(dāng)線程第一次搶占這個(gè)資源時(shí),可能這個(gè)資源被占用,如果此時(shí)掛起這個(gè)線程,可能立刻就發(fā)現(xiàn)資源可用,然后又需要花費(fèi)很長的時(shí)間重新?lián)屨兼i,時(shí)間代價(jià)就會(huì)非常的高。

   所以就有了樂觀鎖的概念,他的核心思路就是,每次不加鎖而是假設(shè)沒有沖突而去完成某項(xiàng)操作,如果因?yàn)闆_突失敗就重試,直到成功為止。在上面的例子中,某個(gè)線程可以不讓出cpu,而是一直while循環(huán),如果失敗就重試,直到成功為止。所以,當(dāng)數(shù)據(jù)爭用不嚴(yán)重時(shí),樂觀鎖效果更好。比如我們要說的AtomicInteger底層同步CAS就是一種樂觀鎖思想的應(yīng)用。

CAS

  CAS就是Compare and Swap的意思,比較并操作。很多的cpu直接支持CAS指令。CAS是項(xiàng)樂觀鎖技術(shù),當(dāng)多個(gè)線程嘗試使用CAS同時(shí)更新同一個(gè)變量時(shí),只有其中一個(gè)線程能更新變量的值,而其它線程都失敗,失敗的線程并不會(huì)被掛起,而是被告知這次競爭中失敗,并可以再次嘗試。CAS有3個(gè)操作數(shù),內(nèi)存值V,預(yù)期值A(chǔ),要修改的新值B。當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時(shí),將內(nèi)存值V修改為B,否則什么都不做。

AtomicInteger

public int a = 1;public boolean compareAndSwapInt(int b) { if (a == 1) { a = b; return true; } return false;}

線程A執(zhí)行到 a==1,正準(zhǔn)備執(zhí)行a = b時(shí),線程B也正在運(yùn)行a = b,并在線程A之前把a(bǔ)修改為2;最后線程A又把a(bǔ)修改成了3。結(jié)果就是兩個(gè)線程同時(shí)修改了變量a,顯然這種結(jié)果是無法符合預(yù)期的,無法確定a的值。 解決方法也很簡單,在compareAndSwapInt方法加鎖同步,變成一個(gè)原子操作,同一時(shí)刻只有一個(gè)線程才能修改變量a。

CAS中的比較和替換是一組原子操作,不會(huì)被外部打斷,先根據(jù)paramLong/paramLong1獲取到內(nèi)存當(dāng)中當(dāng)前的內(nèi)存值V,在將內(nèi)存值V和原值A(chǔ)作比較,要是相等就修改為要修改的值B,屬于硬件級(jí)別的操作,效率比加鎖操作高。

java.util.concurrent.atomic包下的原子操作類都是基于CAS實(shí)現(xiàn)的,接下去我們通過AtomicInteger來看看是如何通過CAS實(shí)現(xiàn)原子操作的:

//jdk1.8實(shí)現(xiàn)public final int getAndAdd(int delta) { return unsafe.getAndAddInt(this, valueOffset, delta);}public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5;}

在jdk1.8中,比較和替換操作放在unsafe類中實(shí)現(xiàn)。

假設(shè)現(xiàn)在線程A和線程B同時(shí)執(zhí)行g(shù)etAndAdd操作:

AtomicInteger里面的value原始值為3,即主內(nèi)存中AtomicInteger的value為3,根據(jù)Java內(nèi)存模型,線程A和線程B各自持有一份value的副本,值為3。線程A通過getIntVolatile(var1, var2)方法獲取到value值3,線程切換,線程A掛起。線程B通過getIntVolatile(var1, var2)方法獲取到value值3,并利用compareAndSwapInt方法比較內(nèi)存值也為3,比較成功,修改內(nèi)存值為2線程切換,線程B掛起。線程A恢復(fù),利用compareAndSwapInt方法比較,發(fā)手里的值3和內(nèi)存值4不一致,此時(shí)value正在被另外一個(gè)線程修改,線程A不能修改value值。線程的compareAndSwapInt實(shí)現(xiàn),循環(huán)判斷,重新獲取value值,因?yàn)関alue是volatile變量,所以線程對(duì)它的修改,線程A總是能夠看到。線程A繼續(xù)利用compareAndSwapInt進(jìn)行比較并替換,直到compareAndSwapInt修改成功返回true。

整個(gè)過程中,利用CAS保證了對(duì)于value的修改的線程安全性。value 在AtomicInteger類中是volatile修飾,保證了多線程下的可見性。 Unsafe是CAS的核心類,Java無法直接訪問底層操作系統(tǒng),而是通過本地(native)方法來訪問。不過盡管如此,JVM還是開了一個(gè)后門,JDK中有一個(gè)類Unsafe,它提供了硬件級(jí)別的原子操作 Unsafe類中的compareAndSwapInt方法 。是一個(gè)本地方法調(diào)用C++代碼


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 日韩欧美高清一区 | 全黄裸片武则天艳史 | 欧美成人高清视频 | 精品一区久久久 | 手机黄色小视频 | 美女视频网站黄色 | 91精品国产777在线观看 | 欧美黄色一级生活片 | 国内精品久久久久久影视8 嫩草影院在线观看网站成人 | 国产精品九九久久一区hh | 羞羞的视频 | 李宗瑞国产福利视频一区 | 99最新网址| 97人操| 国产精品久久久久久久久久东京 | 成人午夜视频在线观看 | 麻豆蜜桃在线观看 | 午夜生活理论片 | 欧洲成人在线视频 | 男女一边摸一边做羞羞视频免费 | 亚洲码无人客一区二区三区 | 深夜影院一级毛片 | 久久精品久久久久 | 国产精品中文在线 | 99re热视频这里只精品 | 老女人碰碰在线碰碰视频 | 免费观看黄色影片 | 国产手机国产手机在线 | 色婷婷tv | 欧美日韩手机在线观看 | 国产精品久久久久免费视频 | 色中射 | 国产jjizz一区二区三区视频 | 欧美女优一区 | 九九热精 | 免费久久久久久久 | 日本娇小videos高潮 | 一级毛片免费观看在线 | www.48xx.com| 成人h精品动漫一区二区三区 | 精品国产一区二区亚洲人成毛片 |