- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- 詳解java 中的CAS與ABA
屬于悲觀(guān)鎖,有共享資源,需要加鎖時(shí),會(huì )以獨占鎖的方式導致其它需要獲取鎖才能執行的線(xiàn)程掛起,等待持有鎖的錢(qián)程釋放鎖。傳統的關(guān)系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫(xiě)鎖等,都是在做操作之前先上鎖。Java中synchronized和ReentrantLock等獨占鎖就是悲觀(guān)鎖的思想。
多線(xiàn)程并發(fā)修改一個(gè)值時(shí)的實(shí)現:
public class SimulatedCAS { //加volatile的目的是利用其happens-before原則,保證線(xiàn)程可見(jiàn)性 private volatile int value; public synchronized int getValue() { return value; } public synchronized int compareAndSwap(int expectedValue, int newValue) { int oldValue = value; if (value == expectedValue) value = newValue; return oldValue; } }
總是假設最好的情況,每次去拿數據的時(shí)候都認為別人不會(huì )修改,所以不會(huì )上鎖,但是在更新的時(shí)候會(huì )判斷一下在此期間別人有沒(méi)有去更新這個(gè)數據,可以使用版本號機制和CAS算法實(shí)現。樂(lè )觀(guān)鎖適用于多讀的應用類(lèi)型,這樣可以提高吞吐量,像數據庫提供的類(lèi)似于write_condition機制,其實(shí)都是提供的樂(lè )觀(guān)鎖。 在Java中java.util.concurrent.atomic包下面的原子變量類(lèi)就是使用了樂(lè )觀(guān)鎖的一種實(shí)現方式CAS實(shí)現的。樂(lè )觀(guān)鎖一般會(huì )使用版本號機制或CAS算法實(shí)現。
public class CasCounter { private SimulatedCAS value; public int getValue() { return value.getValue(); } public int increment() { int oldValue = value.getValue(); while (value.compareAndSwap(oldValue, oldValue + 1) != oldValue) oldValue = value.getValue(); return oldValue + 1; } }
JDK5.0之后加入了java.util.concurrent.atomic 包,其中的AtomicInteger; AtomicLong; AtomicReference; AtomicBoolean 等都是在CAS基礎上實(shí)現的。
public class AtomicTest { private static AtomicInteger atomicInteger = new AtomicInteger(100); private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(99, 0); public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { atomicInteger.compareAndSet(99, 100); atomicInteger.compareAndSet(100, 99); }); Thread thread2 = new Thread(() -> { try { TimeUnit.SECONDS.sleep(1); }catch (InterruptedException e){ e.printStackTrace(); } boolean b = atomicInteger.compareAndSet(99, 100); System.out.println(b); }); thread1.start(); thread2.start(); thread1.join(); thread2.join(); Thread refT1 = new Thread(() -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } atomicStampedReference.compareAndSet(99, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1); atomicStampedReference.compareAndSet(100, 99, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1); }); Thread refT2 = new Thread(() -> { int stamp = atomicStampedReference.getStamp(); System.out.println("before sleep : stamp = " + stamp); // stamp = 0 try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("after sleep : stamp = " + atomicStampedReference.getStamp());//stamp = 1 boolean c3 = atomicStampedReference.compareAndSet(99, 100, stamp, stamp+1); System.out.println(c3); //false }); refT1.start(); refT2.start(); } }
結果如下:
true before sleep : stamp = 0 after sleep : stamp = 2 false
也就是說(shuō)AtomicInteger更新成功,而AtomicStampedReference更新失敗。
以上就是詳解java 中的CAS與ABA的詳細內容,更多關(guān)于java 中的CAS與ABA的資料請關(guān)注腳本之家其它相關(guān)文章!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站