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

Java中的CAS和ABA問題說明

 更新時間:2022年05月07日 10:06:28   作者:lishentao_1122  
這篇文章主要介紹了Java中的CAS和ABA問題說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

1.CAS

1)CAS概念

CAS時Compare And Swap縮寫,即比較與交換是用于實現多線程同步的原子指令,它將內存位置的內容與給定值相比較,相同則修改內存位置的值為新值,而整個操作是調用的UnSafe的compareAndSwapObject、compareAndSwapInt或者compareAndSwapLong完成的,而這些方法都是native修飾的本地方法,是一種系統(tǒng)原語系統(tǒng)支持的操作。

2)CAS產生的影響(無鎖執(zhí)行)

CAS是一種無鎖對象的原子操作,鎖分為樂觀鎖和悲觀鎖,樂觀派抱著幾乎不會發(fā)生修改同一資源的狀態(tài),任意操作同意對象資源,如果遇到修改同一資源的情況,資源不會修改成功,能夠保證資源的安全,而悲觀派會認為同一資源被錯誤修改后會造成不可挽回的局面,故自能有一個線程修改資源,這樣總會對系統(tǒng)性能產生一定的影響,拖慢自行速度,CAS即無鎖執(zhí)行者,被CAS修飾過的資源可以同時被多個線程修改依然能保證系統(tǒng)安全,無鎖不需要等待提高系統(tǒng)性能,jdk提供的CAS原理實現的并發(fā)類Automic系列運用及其原理介紹。

3)Automic并發(fā)類CAS原理代碼分析

首先介紹java的指針操作類UnSafe,Unsafe類是在sun.misc包下,不屬于Java標準。但是很多Java的基礎類庫,包括一些被廣泛使用的高性能開發(fā)庫都是基于Unsafe類開發(fā)的,因為UnSafe使Java像C語言一樣使其擁有操作內存指針的能力,因為操作內存指針容易出錯,故起名UnSafe不安全的類,因此Java官方并不建議使用的,但CAS原理就是UnSafe類中的compareAndSwapObject、compareAndSwapInt和compareAndSwapLong方法實現的,該方法需傳入四個參數:第一個參數代表給定的對象,第二個參數代表給定對象再內存中的偏移量,第三個參數標識對象的期望值,第四個參數標識要修改的值,并發(fā)保重的Automic系列的原子操作類都是使用UnSafe類實現的。

UnSafe源碼如下:

/**
* 第一個參數var1代表給定對象,第二個參數var2代表var1對象在內存中的偏移量,第三個參數var3為期望修改* 的對象舊值,第四個參數var4代表要修改的值或著說是修改后的值。
**/
public final native boolean compareAndSwapObject(Object var1, long var2, Object var3, Object var4);
? ? public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
? ? public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

舉例AtomicInteger源碼實現原理:

AutomicInteger中的getAndSet實現原理解析:

? ? /**
? ? * 調用的UnSafe的getAndSetInt方法,給定值和偏移量和修改的值,
? ? * 獲取修改的值var5作為compareAndSwapInt的第三個參數用來和var1比較相同則執(zhí)行更新操作
? ? * while循環(huán)知道操作成功。
? ? *public final int getAndSetInt(Object var1, long var2, int var4) {
? ? * ? int var5;
? ? * ? do {
? ? * ? ? ? var5 = this.getIntVolatile(var1, var2);
? ? * ? } while(!this.compareAndSwapInt(var1, var2, var5, var4));
? ? *
? ? * ? ?return var5;
? ? *}
? ? **/
? ? public final int getAndSet(int newValue) {
? ? ? ? return unsafe.getAndSetInt(this, valueOffset, newValue);
? ? }
package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;
 
public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;
 
    // 獲取UnSafe對象實例
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //對象在內存中的偏移量
    private static final long valueOffset;
    
    //初始化valueOffset
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    
    //對象屬性值
    private volatile int value;
 
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }
 
    public AtomicInteger() {
    }
 
    /**
    * 調用的UnSafe的getAndSetInt方法,給定值和偏移量和修改的值,
    * 獲取修改的值var5作為compareAndSwapInt的第三個參數用來和var1比較相同則執(zhí)行更新操作
    * while循環(huán)知道操作成功。
    *public final int getAndSetInt(Object var1, long var2, int var4) {
    *   int var5;
    *   do {
    *       var5 = this.getIntVolatile(var1, var2);
    *   } while(!this.compareAndSwapInt(var1, var2, var5, var4));
    *
    *    return var5;
    *}
    **/
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }
 
    //調用UnSafe的compareAndSwapInt方法保證CAS
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
 
    //調用UnSafe的compareAndSwapInt方法保證CAS
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
 
    //調用UnSafe的getAndAddInt再調用UnSafe的getAndSetInt方法保證CAS
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
 
    
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }
    .........
}

4)CAS導致的ABA問題

操作對象,獲取對象后,執(zhí)行CAS操作前,被其他線程修改后,且又修改為原來的對象值,導致CAS忽略其他線程的修改,成功執(zhí)行CAS對象修改,這種情況就叫做ABA問題。

下圖所示:

解決辦法:

AtomicStampedReference類提供了解決辦法,在對象之中又添加了stamp時間戳屬性避免其他線程修改了多次并變回修改前的value值,但對比stamp不同便可知道對象是被修改過的,只有提供屬性值和stamp時間戳相等才能成功執(zhí)行CAS修改操作,里面包裹了一個鍵值對對象AtomicStampedReference.Pair<V> pair類型,pair中值為屬性值,value為stamp時間戳,在執(zhí)行CAS操作時需要提供原值的value和時間戳都相等的情況才能成功執(zhí)行CAS操作。

AtomicMarkableReference類提供了解決辦法,在對象之中又添加了stamp時間戳屬性避免其他線程修改了多次并變回修改前的value值,但對比stamp不同便可知道對象是被修改過的,只有提供屬性值和boolean類型的mark標記相等才能成功執(zhí)行CAS修改操作,里面包裹了一個鍵值對對象AtomicMarkableReference.Pair<V> pair類型,pair中值為屬性值,value為mark是否被修改的標記,在執(zhí)行CAS操作時需要提供原值的value和mark標記都相等的情況才能成功執(zhí)行CAS操作。

本文只介紹AtomicStampedReference類的源碼分析,AtomicMarkableReference類同AtomicStampedReference類原理一樣,

源碼如下:

package java.util.concurrent.atomic;
public class AtomicStampedReference<V> {
   /**
    * 對象值時一個AtomicStampedReference內置對象Pair,包裹了reference和stamp兩個屬性
    */
    private static class Pair<T> {
        final T reference;
        final int stamp;
        private Pair(T reference, int stamp) {
            this.reference = reference;
            this.stamp = stamp;
        }
        static <T> Pair<T> of(T reference, int stamp) {
            return new Pair<T>(reference, stamp);
        }
    }
 
    private volatile Pair<V> pair;
 
    /**
     * 初始化對象并初始化pair 
     */
    public AtomicStampedReference(V initialRef, int initialStamp) {
        pair = Pair.of(initialRef, initialStamp);
    }
    
    /**
     * 比較當前對象屬性值和輸入原始值為真,在比較當前對象的時間stamp與期望的stamp進行比較
     * 如果也想等,就更新值和stamp
     * @param expectedReference 原始值
     * @param newReference 新值
     * @param expectedStamp 期望時間
     * @param newStamp 新時間
     * @return {@code true} if successful
     */
    public boolean compareAndSet(V   expectedReference,
                                 V   newReference,
                                 int expectedStamp,
                                 int newStamp) {
        Pair<V> current = pair;  //賦值當前對象
        return
            expectedReference == current.reference &&
            expectedStamp == current.stamp &&
            ((newReference == current.reference &&
              newStamp == current.stamp) ||
             casPair(current, Pair.of(newReference, newStamp)));
    }
 
    
    // Unsafe mechanics
 
    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
    private static final long pairOffset =
        objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class);
 
    private boolean casPair(Pair<V> cmp, Pair<V> val) {
        return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
    }
 
    static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
                                  String field, Class<?> klazz) {
        try {
            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
        } catch (NoSuchFieldException e) {
            // Convert Exception to corresponding Error
            NoSuchFieldError error = new NoSuchFieldError(field);
            error.initCause(e);
            throw error;
        }
    }
}

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • java中四種生成和解析XML文檔的方法詳解(介紹+優(yōu)缺點比較+示例)

    java中四種生成和解析XML文檔的方法詳解(介紹+優(yōu)缺點比較+示例)

    本篇文章主要介紹了四種生成和解析XML文檔的方法,即:DOM、SAX、JDOM和DOM4J,具有一定的參考價值,有興趣的可以了解一下。
    2016-11-11
  • Java類初始化時機測試方法解析

    Java類初始化時機測試方法解析

    這篇文章主要介紹了Java類初始化時機測試過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • Java異常處理try?catch的基本使用

    Java異常處理try?catch的基本使用

    大家好,本篇文章主要講的是Java異常處理try?catch的基本使用,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-02-02
  • Spring?Boot如何監(jiān)控SQL運行情況?

    Spring?Boot如何監(jiān)控SQL運行情況?

    Druid是Java語言中最好的數據庫連接池,下面這篇文章主要給大家介紹了關于Spring?Boot如何監(jiān)控SQL運行情況的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • 東方通TongWeb結合Spring-Boot使用的實現

    東方通TongWeb結合Spring-Boot使用的實現

    本文主要介紹了東方通TongWeb結合Spring-Boot使用的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-07-07
  • Java實現俄羅斯方塊游戲的示例代碼

    Java實現俄羅斯方塊游戲的示例代碼

    俄羅斯方塊是一個最初由阿列克謝帕吉特諾夫在蘇聯設計和編程的益智類視頻游戲。本文將利用Java實現這一經典的小游戲,感興趣的可以動手試一試
    2022-03-03
  • Java(enum)枚舉用法詳解

    Java(enum)枚舉用法詳解

    本篇文章主要介紹了Java 枚舉用法詳解,枚舉的好處:可以將常量組織起來,統(tǒng)一進行管理。有興趣的可以一起來了解一下。
    2016-11-11
  • Java單利模式與多線程總結歸納

    Java單利模式與多線程總結歸納

    這篇文章主要介紹了Java單利模式與多線程總結歸納 的相關資料,需要的朋友可以參考下
    2016-03-03
  • Java三目運算中隱藏的自動拆裝箱

    Java三目運算中隱藏的自動拆裝箱

    這篇文章主要介紹了Java三目運算中隱藏的自動拆裝箱,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-11-11
  • Java的idea連接mongodb數據庫的詳細教程

    Java的idea連接mongodb數據庫的詳細教程

    這篇文章主要介紹了Java的idea連接mongodb數據庫的詳細教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11

最新評論

新营市| 宣武区| 南溪县| 锦州市| 安福县| 巨野县| 浦城县| 靖江市| 黎城县| 沽源县| 周宁县| 孙吴县| 丰原市| 阳江市| 淮滨县| 怀来县| 洛扎县| 保靖县| 万年县| 黔西| 平塘县| 乐陵市| 农安县| 西城区| 仙桃市| 邯郸县| 东兰县| 江都市| 长寿区| 彩票| 毕节市| 漠河县| 化州市| 遵化市| 舟山市| 黄冈市| 桐乡市| 杭州市| 武夷山市| 六枝特区| 读书|