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

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

一文讀懂Java中的cas是什么

更新時(shí)間:2022-08-04 09:59:02 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1333次

1.CAS的含義

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

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

2.CAS的問題

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

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

3.看AutoInteger的實(shí)現(xiàn)源碼

其實(shí)AutoInteger就是使用了CAS來實(shí)現(xiàn)加1,我們知道如果有一個(gè)共享變量count=1,開5個(gè)線程,每個(gè)線程加20次,結(jié)果一般來說都會(huì)小于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;
}

結(jié)果78

現(xiàn)在修改一個(gè)代碼,將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);
}

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

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

AtomicInteger,AtomicLong,AtomicBoolean.....都在java.util.current.atomic包下面,采用了CAS機(jī)制來實(shí)現(xiàn)加鎖。如果大家想了解更多相關(guān)知識(shí),可以關(guān)注動(dòng)力節(jié)點(diǎn)的多線程教程中的部分內(nèi)容,這是掌握多線程線程鎖種類的必學(xué)內(nèi)容,為我們后面學(xué)習(xí)多線程的更多內(nèi)容打下堅(jiān)實(shí)的基礎(chǔ)。

提交申請(qǐng)后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)

免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 97精品福利视频在线 | 天天综合网天天做天天受 | 婷婷综合 在线 | 黑人巨大精品战中国美女 | 免费黄色福利视频 | 日日干干| 黄色片网站观看 | 亚洲日韩欧洲无码av夜夜摸 | 一级毛片在线观看视频 | 女人18毛片a级毛片免费看一 | 国产亚洲综合一区二区在线 | 免费福利小视频 | 毛片91 | 亚洲人成一区二区不卡 | 青青青在线视频国产 | 人成午夜| 成人亚洲网 | 亚洲成人在线免费视频 | 国产色综合网 | 香蕉亚洲| 国内精品久久久久久麻豆 | 婷婷色九月综合激情丁香 | 久草在线视频精品 | 国产精品久久久久久久伊一 | 日本高清在线精品一区二区三区 | 国产在线精品一区二区高清不卡 | 国产资源站 | 欧美黄视频在线观看 | 狠狠的日视频 | 亚洲视频手机在线 | 日本不卡在线观看 | 久久精品国产精品亚洲艾 | 国产高清国产精品国产k | 亚洲欧美综合久久 | 久久国产精品广西柳州门 | 国产福利精品在线 | 青青热久久久久综合精品 | 免费观看成人久久网免费观看 | 天天操操操 | 黄色在线视频观看 | 日本一级特黄毛片免费视频 |