大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 一文讀懂Java中的cas是什么

一文讀懂Java中的cas是什么

更新時間:2022-08-04 09:59:02 來源:動力節點 瀏覽1183次

1.CAS的含義

CAS是compare and swap的縮寫,即我們所說的比較交換。cas是一種基于鎖的操作,而且是樂觀鎖。在線程鎖分類中,鎖分為樂觀鎖和悲觀鎖。悲觀鎖是將資源鎖住,等一個之前獲得鎖的線程釋放鎖之后,下一個線程才可以訪問。而樂觀鎖采取了一種寬泛的態度,通過某種方式不加鎖來處理資源,比如通過給記錄加version來獲取數據,性能較悲觀鎖有很大的提高。

CAS 操作包含三個操作數 —— 內存位置(V)、預期原值(A)和新值(B)。如果內存地址里面的值和A的值是一樣的,那么就將內存里面的值更新成B。CAS是通過無限循環來獲取數據的,若果在第一輪循環中,a線程獲取地址里面的值被b線程修改了,那么a線程需要自旋,到下次循環才有可能機會執行。

2.CAS的問題

(1)CAS容易造成ABA問題。一個線程a將數值改成了b,接著又改成了a,此時CAS認為是沒有變化,其實是已經變化過了,而這個問題的解決方案可以使用版本號標識,每操作一次version加1。在java5中,已經提供了AtomicStampedReference來解決問題。

(2)CAS造成CPU利用率增加。之前說過了CAS里面是一個循環判斷的過程,如果線程一直沒有獲取到狀態,cpu資源會一直被占用。

3.看AutoInteger的實現源碼

其實AutoInteger就是使用了CAS來實現加1,我們知道如果有一個共享變量count=1,開5個線程,每個線程加20次,結果一般來說都會小于100.

@Test
public void test20() throws InterruptedException {
    for (int i = 1; i <= 5; i++) {
        MyThrend thrend = new MyThrend("thead" + i);
        Thread thread = new Thread(thrend);
        thread.start();
    }
    Thread.sleep(2000);
    System.out.println(MyCount1.count);
}
static class MyThrend implements Runnable {
    private String name;
    MyThrend(String threadName) {
        this.name = threadName;
    }
    @Override
    public void run() {
        for (int i=0;i<20;i++)
        MyCount1.count++;
    }
}
private static class MyCount1 {
    static int count = 0;
}

結果78

現在修改一個代碼,將int變成AtomicInteger

@Test
public void test20() throws InterruptedException {
    for (int i = 1; i <= 5; i++) {
        MyThrend thrend = new MyThrend("thead" + i);
        Thread thread = new Thread(thrend);
        thread.start();
    }
    Thread.sleep(2000);
    System.out.println(MyCount.count.get());
}
static class MyThrend implements Runnable {
    private String name;
    MyThrend(String threadName) {
        this.name = threadName;
    }
    @Override
    public void run() {
        for (int i=0;i<20;i++)
        MyCount.count.getAndIncrement();  //加1方法
    }
}
private static class MyCount {
    static AtomicInteger count = new AtomicInteger(0);
}

每次結果都是100,怎么做到的呢?這里是沒有直接加鎖的,看源碼。

public final int getAndIncrement() {
    return unsafe.getAndAddInt(this, valueOffset, 1);  //第一個參數當前對象地址,第二個參數數據偏移量,第三個參數每次指定默認加1
}
public final int getAndAddInt(Object var1, long var2, int var4) {  //這個方法使用的就是CAS,核心在于循環比較內存里面的值和當前值是否相等,如果相等就用新值覆蓋
    int var5;   
    do {
        var5 = this.getIntVolatile(var1, var2);  //如果a,b線程同時執行這個方法,a線程拿到值1后cpu執行時間到了掛起,b開始執行,也拿到1,但是沒有掛起,接著將值變成了2
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));  //這個時候a線程恢復執行,去比較的時候發現手上的1 和內存里面的值2不等,這個時候他要進行下一個循環,看出來了占用cpu吧
    return var5;
}

AtomicInteger,AtomicLong,AtomicBoolean.....都在java.util.current.atomic包下面,采用了CAS機制來實現加鎖。如果大家想了解更多相關知識,可以關注動力節點的多線程教程中的部分內容,這是掌握多線程線程鎖種類的必學內容,為我們后面學習多線程的更多內容打下堅實的基礎。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 成年男女免费视频网站 | 色四虎| 国产福利视屏 | 欧美精品免费在线观看 | 素人视频在线观看 | 亚洲欧美日韩国产精品影院 | 婷婷亚洲视频 | 一级免费看 | 亚洲国产精品婷婷久久 | 中文字幕亚洲无线码在线一区 | 91久久天天躁狠狠躁夜夜 | 国产高清在线视频一区二区三区 | 色婷婷综合和线在线 | 久久日本精品99久久久 | 天天综合色天天综合网 | 久久精品国产精品亚洲毛片 | 青青青爽视频在线观看入口 | 日韩爱爱小视频 | 日韩欧美亚洲综合久久影院d3 | 美女撒尿毛片免费看 | 九天玄帝诀高清300集免费观看 | 天天操天天摸天天爽 | 黄色一级毛片 | 91久久精一区二区三区大全 | 久久视频精品36线视频在线观看 | 亚洲精品欧美精品中文字幕 | 99r8这里精品热视频免费看 | 婷婷伊人五月 | 国产精品视频在线播放 | 天天谢天天干 | 久久久久久在线 | 99成人国产精品视频 | 欧洲亚洲精品 | 99精品国产高清一区二区 | 久久婷五月综合 | 久草在线视频免费 | 久久99精品久久久久久三级 | 9re视频这里只有精品 | 四虎最新网址入口 | 久久天天躁狠狠躁夜夜躁综合 | 亚洲在线成人 |