成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

CAS(compareAndSwap)原理

wyk1184 / 1902人閱讀

摘要:中對(duì)應(yīng)擁有三個(gè)方法和,他們都被標(biāo)記為它的核心實(shí)現(xiàn)為實(shí)現(xiàn)核心如下位平臺(tái)運(yùn)行的程序在位上會(huì)占用更大的長(zhǎng)度,可以使用壓縮指針,達(dá)到節(jié)約內(nèi)存的目的。只能是一個(gè)變量問(wèn)題。自身提供了來(lái)解決這個(gè)問(wèn)題,原理是添加一個(gè)額外的版本來(lái)做判斷源碼來(lái)自

unsafe中對(duì)應(yīng)擁有三個(gè)方法 compareAndSwapObject ,compareAndSwapIntcompareAndSwapLong ,他們都被標(biāo)記為native

compareAndSwapObject

它的核心實(shí)現(xiàn)為

oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e);

實(shí)現(xiàn)核心如下

inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value,
                                                volatile HeapWord *dest,
                                                oop compare_value) {
  if (UseCompressedOops) {
    narrowOop val = encode_heap_oop(exchange_value);
    narrowOop cmp = encode_heap_oop(compare_value);

    narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp);
    return decode_heap_oop(old);
  } else {
    return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value);
  }
}
UseCompressedOops: 32位平臺(tái)運(yùn)行的程序在64位上會(huì)占用更大的長(zhǎng)度,可以使用 -XX:+UserCompressedOops壓縮指針,達(dá)到節(jié)約內(nèi)存的目的。
compareAndSwapInt

核心代碼如下

return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
compareAndSwapLong

核心代碼如下

if (VM_Version::supports_cx8())
  return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
else {
  jboolean success = false;
  ObjectLocker ol(p, THREAD);
  if (*addr == e) { *addr = x; success = true; }
  return success;
}

supports_cx8:判斷硬件是不是支持8-byte compare-exchange , x86架構(gòu)中通過(guò)cpuid指令來(lái)獲取是否試支持,CMPXCHG8指令 ;SPARC架構(gòu)也是看 (_features & v9_instructions_m)指令的支持情況

Atomic::cmpxchg

無(wú)論是那個(gè)調(diào)用,最終都?xì)w結(jié)到了Atomic上,Atomic.hpp中函數(shù)聲明如下

//比較當(dāng)前的值和目的地址的值,如果比較成功,就把目的地址的值更改為exchange_value,并返回原來(lái)存的值
static jbyte    cmpxchg    (jbyte    exchange_value, volatile jbyte*    dest, jbyte    compare_value);
static jint     cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value);
static jlong    cmpxchg    (jlong    exchange_value, volatile jlong*    dest, jlong    compare_value);
static unsigned int cmpxchg(unsigned int exchange_value, volatile unsigned int* dest, unsigned int compare_value);
static intptr_t cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value);
static void*    cmpxchg_ptr(void*    exchange_value, volatile void*     dest, void*    compare_value);

從Atomic.cpp可以看到在不同的操作系統(tǒng)中有不同的實(shí)現(xiàn)
在 windows_x86中,一種實(shí)現(xiàn)如下

inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  int mp = os::is_MP(); //查看是否是多核
  __asm {
    mov edx, dest
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP(mp)
    cmpxchg dword ptr [edx], ecx
  }
}

linux_x86中,實(shí)現(xiàn)如下

inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  int mp = os::is_MP();
  __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"                    : "=a" (exchange_value)
                    : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
                    : "cc", "memory");
  return exchange_value;
}

可以看到最終都是使用操作系統(tǒng)對(duì)應(yīng)的指令來(lái)完成

都在哪兒用了


可以看到Atomic的實(shí)現(xiàn)就是用的CAS,比如AtomicIntegerincrementAndGet

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

這種一直循環(huán)的操作也稱(chēng)作自旋

CAS的缺點(diǎn)

如果一直沒(méi)有成功,則一直循環(huán),給CPU帶來(lái)很大的開(kāi)銷(xiāo)。

只能是一個(gè)變量

ABA問(wèn)題。一個(gè)變量取值為A,恰巧另一個(gè)線程將它換成了B然后又換回來(lái)了,這個(gè)時(shí)候再讀取還是A,實(shí)際上是改變了值。java自身提供了AtomicStampedReference來(lái)解決這個(gè)問(wèn)題,原理是添加一個(gè)額外的版本來(lái)做判斷

源碼來(lái)自jdk1.7

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72727.html

相關(guān)文章

  • java高并發(fā)系列 - 第21天:java中的CAS操作,java并發(fā)的基石

    摘要:方法由兩個(gè)參數(shù),表示期望的值,表示要給設(shè)置的新值。操作包含三個(gè)操作數(shù)內(nèi)存位置預(yù)期原值和新值。如果處的值尚未同時(shí)更改,則操作成功。中就使用了這樣的操作。上面操作還有一點(diǎn)是將事務(wù)范圍縮小了,也提升了系統(tǒng)并發(fā)處理的性能。 這是java高并發(fā)系列第21篇文章。 本文主要內(nèi)容 從網(wǎng)站計(jì)數(shù)器實(shí)現(xiàn)中一步步引出CAS操作 介紹java中的CAS及CAS可能存在的問(wèn)題 悲觀鎖和樂(lè)觀鎖的一些介紹及數(shù)據(jù)庫(kù)...

    zorro 評(píng)論0 收藏0
  • Java并發(fā)核心淺談

    摘要:耐心看完的你或多或少會(huì)有收獲并發(fā)的核心就是包,而的核心是抽象隊(duì)列同步器,簡(jiǎn)稱(chēng),一些鎖啊信號(hào)量啊循環(huán)屏障啊都是基于。 耐心看完的你或多或少會(huì)有收獲! Java并發(fā)的核心就是 java.util.concurrent 包,而 j.u.c 的核心是AbstractQueuedSynchronizer抽象隊(duì)列同步器,簡(jiǎn)稱(chēng) AQS,一些鎖啊!信號(hào)量?。⊙h(huán)屏障??!都是基于AQS。而 AQS 又是...

    cppowboy 評(píng)論0 收藏0
  • Java并發(fā)編程-原子操作

    摘要:這個(gè)規(guī)則比較好理解,無(wú)論是在單線程環(huán)境還是多線程環(huán)境,一個(gè)鎖處于被鎖定狀態(tài),那么必須先執(zhí)行操作后面才能進(jìn)行操作。線程啟動(dòng)規(guī)則獨(dú)享的方法先行于此線程的每一個(gè)動(dòng)作。 1. 指令重排序 關(guān)于指令重排序的概念,比較復(fù)雜,不好理解。我們從一個(gè)例子分析: public class SimpleHappenBefore { /** 這是一個(gè)驗(yàn)證結(jié)果的變量 */ private st...

    SillyMonkey 評(píng)論0 收藏0
  • CAS也是鎖

    摘要:先比較,發(fā)現(xiàn)與預(yù)期一致,說(shuō)明沒(méi)有其他線程改動(dòng)過(guò),于是就交換如果不一致說(shuō)明改動(dòng)過(guò),就再來(lái)一次,如此往復(fù)。所謂無(wú)鎖是在層面上沒(méi)有鎖,但其實(shí)在操作系統(tǒng)的指令層面是加了鎖的。這個(gè)鎖比上的鎖性能好很多。 CAS(CompareAndSwap)顧名思義比較再交換。先比較,發(fā)現(xiàn)與預(yù)期一致,說(shuō)明沒(méi)有其他線程改動(dòng)過(guò),于是就交換;如果不一致說(shuō)明改動(dòng)過(guò),就再來(lái)一次,如此往復(fù)。 int prev, next;...

    Flands 評(píng)論0 收藏0
  • AbstractQueuedSynchronizer理解之一(ReentrantLock)

    摘要:有了這個(gè)基礎(chǔ),才能發(fā)揮作用,使得在節(jié)點(diǎn)取消和異常時(shí)能夠保證隊(duì)列在多線程下的完整性。 Doug Lea是JDK中concurrent工具包的作者,這位大神是誰(shuí)可以自行g(shù)oogle。 本文淺析ReentrantLock(可重入鎖)的原理 Lock接口 showImg(https://segmentfault.com/img/bV2671?w=276&h=176); Lock接口定義了這幾個(gè)...

    learning 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<