<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 12, comments - 8, trackbacks - 0, articles - 5
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    [轉(zhuǎn)]CAS原理

    Posted on 2010-11-18 15:16 楊羅羅 閱讀(3126) 評(píng)論(1)  編輯  收藏 所屬分類: java.thread

    在JDK 5之前Java語言是靠synchronized關(guān)鍵字保證同步的,這會(huì)導(dǎo)致有鎖(后面的章節(jié)還會(huì)談到鎖)。

    鎖機(jī)制存在以下問題:

    (1)在多線程競(jìng)爭下,加鎖、釋放鎖會(huì)導(dǎo)致比較多的上下文切換和調(diào)度延時(shí),引起性能問題。

    (2)一個(gè)線程持有鎖會(huì)導(dǎo)致其它所有需要此鎖的線程掛起。

    (3)如果一個(gè)優(yōu)先級(jí)高的線程等待一個(gè)優(yōu)先級(jí)低的線程釋放鎖會(huì)導(dǎo)致優(yōu)先級(jí)倒置,引起性能風(fēng)險(xiǎn)。

    volatile是不錯(cuò)的機(jī)制,但是volatile不能保證原子性。因此對(duì)于同步最終還是要回到鎖機(jī)制上來。

    獨(dú)占鎖是一種悲觀鎖,synchronized就是一種獨(dú)占鎖,會(huì)導(dǎo)致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖。而另一個(gè)更加有效的鎖就是樂觀鎖。所謂觀鎖就是,每次不加鎖而是假設(shè)沒有沖突而去完成某項(xiàng)操作,如果因?yàn)闆_突失敗就重試,直到成功為止。

    CAS 操作

    上面的樂觀鎖用到的機(jī)制就是CAS,Compare and Swap。

    CAS有3個(gè)操作數(shù),內(nèi)存值V,舊的預(yù)期值A(chǔ),要修改的新值B。當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時(shí),將內(nèi)存值V修改為B,否則什么都不做。

    非阻塞算法 (nonblocking algorithms)

    一個(gè)線程的失敗或者掛起不應(yīng)該影響其他線程的失敗或掛起的算法。

    現(xiàn)代的CPU提供了特殊的指令,可以自動(dòng)更新共享數(shù)據(jù),而且能夠檢測(cè)到其他線程的干擾,而 compareAndSet() 就用這些代替了鎖定。

    拿出AtomicInteger來研究在沒有鎖的情況下是如何做到數(shù)據(jù)正確性的。

    private volatile int value;

    首先毫無以為,在沒有鎖的機(jī)制下可能需要借助volatile原語,保證線程間的數(shù)據(jù)是可見的(共享的)。這樣才獲取變量的值的時(shí)候才能直接讀取。

    public final int get() {
            return value;
        }

    然后來看看++i是怎么做到的。

    public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }

    在這里采用了CAS操作,每次從內(nèi)存中讀取數(shù)據(jù)然后將此數(shù)據(jù)和+1后的結(jié)果進(jìn)行CAS操作,如果成功就返回結(jié)果,否則重試直到成功為止。

    而compareAndSet利用JNI來完成CPU指令的操作。

    public final boolean compareAndSet(int expect, int update) {   
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }

    整體的過程就是這樣子的,利用CPU的CAS指令,同時(shí)借助JNI來完成Java的非阻塞算法。其它原子操作都是利用類似的特性完成的。

    而整個(gè)J.U.C都是建立在CAS之上的,因此對(duì)于synchronized阻塞算法,J.U.C在性能上有了很大的提升。

    CAS看起來很爽,但是會(huì)導(dǎo)致“ABA問題”。

    CAS算法實(shí)現(xiàn)一個(gè)重要前提需要取出內(nèi)存中某時(shí)刻的數(shù)據(jù),而在下時(shí)刻比較并替換,那么在這個(gè)時(shí)間差類會(huì)導(dǎo)致數(shù)據(jù)的變化

    比如說一個(gè)線程one從內(nèi)存位置V中取出A,這時(shí)候另一個(gè)線程two也從內(nèi)存中取出A,并且two進(jìn)行了一些操作變成了B,然后two又將V位置的數(shù)據(jù)變成A,這時(shí)候線程one進(jìn)行CAS操作發(fā)現(xiàn)內(nèi)存中仍然是A,然后one操作成功。盡管線程one的CAS操作成功,但是不代表這個(gè)過程就是沒有問題的。如果鏈表的頭在變化了兩次后恢復(fù)了原值,但是不代表鏈表就沒有變化。因此前面提到的原子操作AtomicStampedReference/AtomicMarkableReference就很有用了。這允許一對(duì)變化的元素進(jìn)行原子操作。


    評(píng)論

    # re: [轉(zhuǎn)]CAS原理  回復(fù)  更多評(píng)論   

    2012-10-16 17:24 by 超凡
    好東西!
    主站蜘蛛池模板: 亚洲成av人在线观看网站| 女人毛片a级大学毛片免费| 亚洲AV无码精品无码麻豆| 日日麻批免费40分钟日本的| 亚洲精品国产精品| 国产亚洲成av人片在线观看| 中文字幕av无码无卡免费| 色婷婷综合缴情综免费观看| 亚洲精品第五页中文字幕| 国产精品麻豆免费版| 日本免费久久久久久久网站| 亚洲精品天堂无码中文字幕| 亚洲AV永久精品爱情岛论坛| 扒开双腿猛进入爽爽免费视频| 91成人免费观看在线观看| 亚洲熟妇AV一区二区三区宅男| 亚洲精品无码午夜福利中文字幕| 免费做爰猛烈吃奶摸视频在线观看| 国产男女爽爽爽免费视频| 久久亚洲精品专区蓝色区| 亚洲av之男人的天堂网站| 国产一级淫片免费播放电影| 99免费视频观看| h片在线观看免费| 亚洲国产成人无码AV在线| 亚洲色图在线播放| 一本色道久久综合亚洲精品| 欧洲精品免费一区二区三区| 色片在线免费观看| 免费无码黄网站在线看| 美女视频黄视大全视频免费的| 亚洲人成在久久综合网站| 久久久久亚洲AV成人无码| 亚洲国产精品尤物yw在线| 毛片基地免费观看| 99久久99久久精品免费看蜜桃| 久久精品视频免费| aa在线免费观看| 青青草国产免费国产是公开 | 亚洲人成在久久综合网站| 亚洲成人午夜在线|