多線程-CAS

一豹休、什么是CAS炊昆?

CAS,全稱Compare And Swap(比較與交換)威根,解決多線程并行情況下使用鎖造成性能損耗的一種機制窑眯。
CAS 操作包含三個操作數 —— 內存位置(V)、預期原值(A)和新值(B)医窿。 如果內存位置的值與預期原值相匹配磅甩,那么處理器會自動將該位置值更新為新值 。否則姥卢,處理器不做任何操作卷要。無論哪種情況,它都會在 CAS 指令之前返回該 位置的值

二独榴、CAS的目的

利用CPU的CAS指令僧叉,同時借助JNI來完成Java的非阻塞算法。其它原子操作都是利用類似的特性完成的棺榔。而整個J.U.C都是建立在CAS之上的瓶堕,因此對于synchronized阻塞算法,J.U.C在性能上有了很大的提升症歇。

三郎笆、CAS(compareAndSwap)的原理探究

CAS的實現(xiàn)主要在JUC中的atomic包,我們以AtomicInteger類為例:

  /**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

通過代碼追溯忘晤,可以看出JAVA中的CAS操作都是通過sun包下Unsafe類實現(xiàn)宛蚓,而Unsafe類中的方法都是native方法,由JVM本地實現(xiàn)设塔,所以最終的實現(xiàn)是基于C凄吏、C++在操作系統(tǒng)之上操作

Unsafe類

java不能直接訪問操作系統(tǒng)底層,而是通過本地方法來訪問闰蛔。Unsafe類提供了硬件級別的原子操作痕钢,主要提供了以下功能:
1、通過Unsafe類可以分配內存序六,可以釋放內存任连;
類中提供的3個本地方法allocateMemory、reallocateMemory难咕、freeMemory分別用于分配內存课梳,擴充內存和釋放內存距辆,與C語言中的3個方法對應余佃。
2暮刃、可以定位對象某字段的內存位置,也可以修改對象的字段值爆土,即使它是私有的椭懊;
3、掛起與恢復
將一個線程進行掛起是通過park方法實現(xiàn)的步势,調用 park后氧猬,線程將一直阻塞直到超時或者中斷等條件出現(xiàn)。unpark可以終止一個掛起的線程坏瘩,使其恢復正常盅抚。整個并發(fā)框架中對線程的掛起操作被封裝在 LockSupport類中,LockSupport類中有各種版本pack方法倔矾,但最終都調用了Unsafe.park()方法妄均。

public class LockSupport {
    public static void unpark(Thread thread) {
        if (thread != null)
            unsafe.unpark(thread);
    }

    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        unsafe.park(false, 0L);
        setBlocker(t, null);
    }

    public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            Thread t = Thread.currentThread();
            setBlocker(t, blocker);
            unsafe.park(false, nanos);
            setBlocker(t, null);
        }
    }

    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        unsafe.park(true, deadline);
        setBlocker(t, null);
    }

    public static void park() {
        unsafe.park(false, 0L);
    }

    public static void parkNanos(long nanos) {
        if (nanos > 0)
            unsafe.park(false, nanos);
    }

    public static void parkUntil(long deadline) {
        unsafe.park(true, deadline);
    }
}

4、CAS操作

/**
     * Atomically update Java variable to <tt>x</tt> if it is currently
     * holding <tt>expected</tt>.
     * @return <tt>true</tt> if successful
     */
    public final native boolean compareAndSwapObject(Object o, long offset,
                                                     Object expected,
                                                     Object x);

    /**
     * Atomically update Java variable to <tt>x</tt> if it is currently
     * holding <tt>expected</tt>.
     * @return <tt>true</tt> if successful
     */
    public final native boolean compareAndSwapInt(Object o, long offset,
                                                  int expected,
                                                  int x);

    /**
     * Atomically update Java variable to <tt>x</tt> if it is currently
     * holding <tt>expected</tt>.
     * @return <tt>true</tt> if successful
     */
    public final native boolean compareAndSwapLong(Object o, long offset,
                                                   long expected,
                                                   long x);

四哪自、CAS機制的優(yōu)缺點

4.1 優(yōu)點
CAS是一種樂觀鎖丰包,而且是一種非阻塞的輕量級的樂觀鎖,什么是非阻塞式的呢壤巷?其實就是一個線程想要獲得鎖邑彪,對方會給一個回應表示這個鎖能不能獲得。在資源競爭不激烈的情況下性能高胧华,相比synchronized重量鎖寄症,synchronized會進行比較復雜的加鎖,解鎖和喚醒操作矩动。

4.2 缺點
1)循環(huán)時間長開銷大瘸爽,占用CPU資源

2)只能保證一個共享變量的原子操作

3)ABA問題
如線程1從內存X中取出A,這時候另一個線程2也從內存X中取出A铅忿,并且線程2進行了一些操作將內存X中的值變成了B剪决,然后線程2又將內存X中的數據變成A,這時候線程1進行CAS操作發(fā)現(xiàn)內存X中仍然是A檀训,然后線程1操作成功柑潦。雖然線程1的CAS操作成功,但是整個過程就是有問題的峻凫。比如鏈表的頭在變化了兩次后恢復了原值渗鬼,但是不代表鏈表就沒有變化。

ABA問題解決方案:
1荧琼、添加版本號
2譬胎、AtomicStampedReference
java并發(fā)包為了解決這個問題差牛,提供了一個帶有標記的原子引用類“AtomicStampedReference”,它可以通過控制變量值的版本來保證CAS的正確性堰乔。因此偏化,在使用CAS前要考慮清楚“ABA”問題是否會影響程序并發(fā)的正確性,如果需要解決ABA問題镐侯,改用傳統(tǒng)的互斥同步可能會比原子類更高效侦讨。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市苟翻,隨后出現(xiàn)的幾起案子韵卤,更是在濱河造成了極大的恐慌,老刑警劉巖崇猫,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沈条,死亡現(xiàn)場離奇詭異,居然都是意外死亡诅炉,警方通過查閱死者的電腦和手機蜡歹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門敞葛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熊尉,“玉大人,你說我怎么就攤上這事辐啄〕浩牵” “怎么了景鼠?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長痹扇。 經常有香客問我铛漓,道長,這世上最難降的妖魔是什么鲫构? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任浓恶,我火速辦了婚禮,結果婚禮上结笨,老公的妹妹穿的比我還像新娘包晰。我一直安慰自己,他們只是感情好炕吸,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布伐憾。 她就那樣靜靜地躺著,像睡著了一般赫模。 火紅的嫁衣襯著肌膚如雪树肃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天瀑罗,我揣著相機與錄音胸嘴,去河邊找鬼雏掠。 笑死,一個胖子當著我的面吹牛劣像,可吹牛的內容都是我干的乡话。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼驾讲,長吁一口氣:“原來是場噩夢啊……” “哼蚊伞!你這毒婦竟也來了席赂?” 一聲冷哼從身側響起吮铭,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颅停,沒想到半個月后谓晌,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡癞揉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年纸肉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喊熟。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡柏肪,死狀恐怖,靈堂內的尸體忽然破棺而出芥牌,到底是詐尸還是另有隱情烦味,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布壁拉,位于F島的核電站谬俄,受9級特大地震影響,放射性物質發(fā)生泄漏弃理。R本人自食惡果不足惜溃论,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痘昌。 院中可真熱鬧钥勋,春花似錦、人聲如沸辆苔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姑子。三九已至乎婿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間街佑,已是汗流浹背谢翎。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工捍靠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人森逮。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓榨婆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親褒侧。 傳聞我的和親對象是個殘疾皇子良风,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內容