說到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)載請注明出處。