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

詳解java 中的CAS與ABA

 更新時間:2021年05月10日 09:56:11   作者:開發(fā)架構二三事  
這篇文章主要介紹了java 中的CAS與ABA的相關資料,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下

1. 獨占鎖:

屬于悲觀鎖,有共享資源,需要加鎖時,會以獨占鎖的方式導致其它需要獲取鎖才能執(zhí)行的線程掛起,等待持有鎖的錢程釋放鎖。傳統(tǒng)的關系型數(shù)據(jù)庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。Java中synchronized和ReentrantLock等獨占鎖就是悲觀鎖的思想。

1.1 樂觀鎖的操作

多線程并發(fā)修改一個值時的實現(xiàn):

public class SimulatedCAS {
	//加volatile的目的是利用其happens-before原則,保證線程可見性
     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;
     }
}

2. 樂觀鎖:

總是假設最好的情況,每次去拿數(shù)據(jù)的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),可以使用版本號機制和CAS算法實現(xiàn)。樂觀鎖適用于多讀的應用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫提供的類似于write_condition機制,其實都是提供的樂觀鎖。 在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現(xiàn)方式CAS實現(xiàn)的。樂觀鎖一般會使用版本號機制或CAS算法實現(xiàn)。

2.1 CAS操作

  1. CAS 操作包含三個操作數(shù) —— 內(nèi)存位置(V)、預期原值(A)和新值(B)。如果內(nèi)存位置的值與預期原值相匹配,那么處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。無論哪種情況,它都會在 CAS 指令之前返回該位置的值。(在 CAS 的一些特殊情況下將僅返回 CAS 是否成功,而不提取當前值。)CAS 有效地說明了“我認為位置 V 應該包含值 A;如果包含該值,則將 B 放到這個位置;否則,不要更改該位置,只告訴我這個位置現(xiàn)在的值即可。”
  2. 通常將 CAS 用于同步的方式是從地址 V 讀取值 A,執(zhí)行多步計算來獲得新值 B,然后使用 CAS 將 V 的值從 A 改為 B。如果 V 處的值尚未同時更改,則 CAS 操作成功。
  3. 類似于 CAS 的指令允許算法執(zhí)行讀-修改-寫操作,而無需害怕其他線程同時修改變量,因為如果其他線程修改變量,那么 CAS 會檢測它(并失敗),算法可以對該操作重新計算。 CAS實現(xiàn)計數(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;
    }
}

3. 原子變量類

JDK5.0之后加入了java.util.concurrent.atomic 包,其中的AtomicInteger; AtomicLong; AtomicReference; AtomicBoolean 等都是在CAS基礎上實現(xiàn)的。

4. CAS的缺陷

  1. 循環(huán)時間太長,如果自旋長時間不成功,會給cpu帶來極大的開銷,有興趣的可以使用JMH測試下AtomicLong 和 LongAdder的性能。
  2. ABA問題: CAS需要檢查待操作值有沒有發(fā)生改變,如果沒有發(fā)生改變則更新。 但是存在這樣一種情況:如果一個值原來是A,變成了B,然后又變成了A,那么在CAS檢查的時候會發(fā)現(xiàn)沒有改變,但是實質上它已經(jīng)發(fā)生了改變,這就是所謂的ABA問題。 在運用CAS做Lock-Free操作中有一個經(jīng)典的ABA問題:比如線程1從內(nèi)存位置V中取出A,這時另一個線程2也從內(nèi)存中取出A,并且線程2進行了操作之后變成了B,然線程2又將V位置數(shù)據(jù)變成了A,這時候線程1進行CAS操作發(fā)現(xiàn)內(nèi)存中仍然是A,然后線程1 操作成功??瓷先ナ浅晒α?,實際上有隱藏的問題: 現(xiàn)有一個用單向鏈表實現(xiàn)的FIFO堆棧,棧頂為A,這時線程1已經(jīng)知道A.next為B,然后希望用CAS將棧頂替換為B,在線程1執(zhí)行上面這條指令之前,線程2 介入,將A、B出棧,再push D、C、A,此時A位于棧頂,B已經(jīng)不在棧中;此時線程1執(zhí)行CAS,發(fā)現(xiàn)棧頂仍為A,所以CAS成功,即將棧頂變成B,但實際上此時B與 當前棧中元素D、C沒有關系,B.next為null,這樣一來就直接把C、D丟掉了。 對于ABA問題其解決方案是加上版本號,即在每個變量都加上一個版本號,每次改變時加1,即A —> B —> A,變成A(1) —> B(2) —> A(3)。 java中AtomicStampedReference也實現(xiàn)了這個作用,它通過包裝[E,Integer]的元組來對對象標記版本戳stamp,從而避免ABA問題。
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

也就是說AtomicInteger更新成功,而AtomicStampedReference更新失敗。

以上就是詳解java 中的CAS與ABA的詳細內(nèi)容,更多關于java 中的CAS與ABA的資料請關注腳本之家其它相關文章!

相關文章

  • maven多模塊打包注意事項詳解

    maven多模塊打包注意事項詳解

    這篇文章主要為大家介紹了maven多模塊打包注意事項詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • Spring?Security?過濾器注冊脈絡梳理

    Spring?Security?過濾器注冊脈絡梳理

    這篇文章主要介紹了Spring?Security過濾器注冊脈絡梳理,Spring?Security在Servlet的過濾鏈中注冊了一個過濾器FilterChainProxy,它會把請求代理到Spring?Security自己維護的多個過濾鏈,每個過濾鏈會匹配一些URL,如果匹配則執(zhí)行對應的過濾器
    2022-08-08
  • Java數(shù)組的運用詳解

    Java數(shù)組的運用詳解

    這篇文章主要給大家介紹了關于Java中數(shù)組的定義和使用的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-08-08
  • Spring中的攔截器HandlerInterceptor詳細解析

    Spring中的攔截器HandlerInterceptor詳細解析

    這篇文章主要介紹了Spring中的攔截器HandlerInterceptor詳細解析,HandlerInterceptor 是 Spring 框架提供的一個攔截器接口,用于在請求處理過程中攔截和處理請求,需要的朋友可以參考下
    2024-01-01
  • Elasticsearch(ES)多種查詢方式案例

    Elasticsearch(ES)多種查詢方式案例

    Elasticsearch是一個分布式的RESTful搜索和分析引擎,可讓您輕松地大規(guī)模存儲,搜索和分析,這篇文章主要給大家介紹了關于Elasticsearch(ES)多種查詢方式的相關資料,需要的朋友可以參考下
    2023-09-09
  • SpringBoot自動配置Quartz的實現(xiàn)步驟

    SpringBoot自動配置Quartz的實現(xiàn)步驟

    本文主要介紹了SpringBoot自動配置Quartz的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Java高級特性之反射機制實例詳解

    Java高級特性之反射機制實例詳解

    這篇文章主要介紹了Java高級特性之反射機制,結合實例形式詳細分析了Java反射機制原理、功能、使用方法及相關操作注意事項,需要的朋友可以參考下
    2018-08-08
  • Spring?AOPr如何打通兩個切面之間的通信

    Spring?AOPr如何打通兩個切面之間的通信

    本文主要介紹了Spring?AOPr如何打通兩個切面之間的通信,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-03-03
  • Java中生成不重復隨機數(shù)的四種方法舉例詳解

    Java中生成不重復隨機數(shù)的四種方法舉例詳解

    在Java編程中獲取隨機數(shù)是常見的需求,這篇文章主要介紹了Java中生成不重復隨機數(shù)的四種方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-04-04
  • java使用poi在excel單元格添加超鏈接設置字體顏色的方法

    java使用poi在excel單元格添加超鏈接設置字體顏色的方法

    這篇文章主要介紹了java使用poi在excel單元格添加超鏈接,設置字體顏色,poi功能還是很強大的,基本能想到的功能都能通過poi實現(xiàn),本文結合實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2023-09-09

最新評論

河南省| 桐柏县| 赤峰市| 长寿区| 辉南县| 南汇区| 康乐县| 寻甸| 梧州市| 肃北| 阿克陶县| 海南省| 永宁县| 嘉峪关市| 孝昌县| 彭水| 永平县| 渭南市| 自治县| 许昌市| 昆明市| 满城县| 长岛县| 清水河县| 乐东| 漳浦县| 巫山县| 台江县| 九寨沟县| 原平市| 韩城市| 安宁市| 德江县| 合阳县| 莒南县| 鄢陵县| 沂水县| 巴林右旗| 寿宁县| 颍上县| 甘泉县|