Java并發(fā)編程——AtomicReference,解決并發(fā)修改多個屬性(轉(zhuǎn))

說到CAS理論,在java中我們第一個就想到了atomic類,一般常見的有AtomicInteger、AtomicBoolean等java.util.concurrent包下面的類,但是這個只能并發(fā)修改一個屬性,如果我需要對多個屬性同時(shí)進(jìn)行并發(fā)修改,并且保證原子性呢?

AtomicReference 了解下?

AtomicReference也是java.util.concurrent包下的類,跟AtomicInteger等是一樣的,也是基于CAS無鎖理論實(shí)現(xiàn)的,但是不同的是 AtomicReference 是操控多個屬性的原子性的并發(fā)類

在看看如何使用之前,我們先來介紹一個方法:

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

官方的解釋是:

Atomically sets the value to the given updated value

主要的作用是通過比對兩個對象,然后更新為新的對象

這里需要注意下,這里的比對兩個對象,比對的方式不是equals而是==,意味著比對的是內(nèi)存的中地址,這個我們可以通過unsafe.compareAndSwapObject()方法查看,他是一個native方法

了解了上面的方法,我們來看下AtomicReference是如何使用的

模擬一個場景,在高并發(fā)的場景中,根據(jù)業(yè)務(wù)的需要,要求同時(shí)更新sequence和timestamp

/**
 * Copyright ? 2018 五月工作室. All rights reserved.
 *
 * @Project: tools
 * @ClassName: AtomicReferenceDemo
 * @Package: com.amos.tools.common.bean
 * @author: zhuqb
 * @Description: 主要用來展示AtomicReference使用方法
 * @date: 2019/9/11 0011 上午 9:46
 * @Version: V1.0
 */
public class AtomicReferenceDemo {

    private Reference reference;

    private AtomicReference<Reference> atomicReference;

    /**
     * 構(gòu)建器中初始化AtomicReference
     *
     * @param reference
     */
    public AtomicReferenceDemo(Reference reference) {
        this.reference = reference;
        this.atomicReference = new AtomicReference<>(reference);
    }

    public void atomic(Reference reference) {
        Reference referenceOld;
        Reference referenceNew;

        long sequence;
        long timestamp;

        while (true) {
            referenceOld = this.atomicReference.get();
            sequence = referenceOld.getSequence();
            sequence++;
            timestamp = System.currentTimeMillis();

            referenceNew = new Reference(sequence, timestamp);
            /**
             * 比較交換
             */
            if (this.atomicReference.compareAndSet(referenceOld, referenceNew)) {
                reference.setSequence(sequence);
                reference.setTimestamp(timestamp);
                break;
            }
        }
    }
}

/**
 * 業(yè)務(wù)場景模擬
 * 序列需要自增并且時(shí)間需要更新成最新的時(shí)間戳
 */
@Data
@AllArgsConstructor
class Reference {
    /**
     * 序列
     */
    private long sequence;
    /**
     * 時(shí)間戳
     */
    private long timestamp;
}

上述代碼的邏輯如下:

獲取并緩存原來的變量,這個變量包含原來的序列和時(shí)間戳
基于原來的變量來更新新的時(shí)間戳和序列
計(jì)算后,使用CAS操作更新原來的變量,更新的過程中,需要傳遞保存原來的變量
如果保存的原來變量被其他線程修改了,就需要在這里重新拿到最新的變量,并再次計(jì)算和重試更新

作者:AmosZhu
鏈接:http://www.itdecent.cn/p/3f7485ddb974
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容