Java的原子類
JUC并發(fā)包中提供了一系列原子性操作類,這些類都是使用非阻塞算法 CAS 實(shí)現(xiàn)的,比使用鎖性能有提升。具體實(shí)現(xiàn)大致相同。
原子更新基本類型
AtomicBoolean、AtomicInteger、AtomicLong
關(guān)鍵實(shí)現(xiàn)代碼
public class AtomicLong extends Number implements java.io.Serializable {
private static final long serialVersionUID = 1927816293512124184L;
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long VALUE = U.objectFieldOffset(AtomicLong.class, "value");
private volatile long value;
···
}
核心方法
public final boolean compareAndSet(long expectedValue, long newValue) {
return U.compareAndSetLong(this, VALUE, expectedValue, newValue);
}
public final long getAndIncrement() {
return U.getAndAddLong(this, VALUE, 1L);
}
public final long getAndDecrement() {
return U.getAndAddLong(this, VALUE, -1L);
}
public final long incrementAndGet() {
return U.getAndAddLong(this, VALUE, 1L) + 1L;
}
public final long decrementAndGet() {
return U.getAndAddLong(this, VALUE, -1L) - 1L;
}
原子更新數(shù)組類型
AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
調(diào)用構(gòu)造方法時(shí),會(huì)對(duì)參數(shù)數(shù)組拷貝一次。
原子更新引用類型
AtomicReference (存在ABA問(wèn)題)
AtomicStampedReference(帶有時(shí)間戳,處理ABA問(wèn)題)
AtomicMarkableReference(通過(guò)添加帶有對(duì)象是否被修改的boolean值,處理ABA問(wèn)題)
例子:
public class HelloWorld {
public static void main(String[] args) {
User user1 = new User();
user1.setAge(14);
user1.setName("hello");
AtomicReference<User> userAtomicReference = new AtomicReference<>(user1);
User user2 = new User();
user2.setName("world");
user2.setAge(34);
userAtomicReference.compareAndSet(user1,user2);
System.out.println(userAtomicReference.get());
}
}
class User{
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

原子更新類字段類型
AtomicIntegerFieldUpdater AtomicLongFieldUpdater AtomicReferenceFieldUpdater
優(yōu)化后的原子操作類
LongAdder、LongAccumulator、DoubleAdder、DoubleAccumulator
AtomicLong 類使用 CAS 提供非阻塞原子操作,比起鎖已經(jīng)優(yōu)化了很多,但使用 AtomicLong 在多線程環(huán)境下會(huì)造成線程不斷自旋嘗試(源碼使用無(wú)限循環(huán)),浪費(fèi) CPU 資源。為了解決此問(wèn)題,LongAdder 類在內(nèi)部維護(hù)的多個(gè) Cell 元素來(lái)分擔(dān)對(duì)單個(gè)變量進(jìn)行爭(zhēng)奪的開(kāi)銷。、
LongAdder 類繼承自 Striped64 類,實(shí)現(xiàn)序列化。Striped64內(nèi)部維護(hù)著三個(gè)變量
volatile long base;//初始值
volatile int cellsBusy;//用來(lái)實(shí)現(xiàn)自旋鎖,狀態(tài)值 0 與 1
volatile Cell[] cells;//原子可見(jiàn)的Cell元素
底層通過(guò) CAS 算法實(shí)現(xiàn)非阻塞原子操作
@sun.misc.Contented//避免Cell數(shù)組的偽分享出現(xiàn),導(dǎo)致降低并發(fā)訪問(wèn)的性能
static final class Cell{
volatile long value;
Cell(long x){
value = x;
}
final boolean cas(long cmp,long val){
return UNSAFE.compareAndSwapLong(this,valueOffest,cmp,val);//使用Unsafe類實(shí)現(xiàn)對(duì)Cell元素操作的原子性
}
}
在 LongAdder 類中維護(hù)的變量 cells 采用延遲初始化策略。cells 的元素通過(guò) cas 函數(shù)的 CAS 操作達(dá)到原子性更新。
public long sum();//返回當(dāng)前的值,內(nèi)部所有 cell 和 base 的和,相加時(shí)未使用鎖,返回值不精確,此時(shí)可能有 cell 被修改。多線程有問(wèn)題。+
public void reset();//重置,base 置0 ,若 cells 的元素有值則置0.
public long sumThenReset(); //累加后置0,多線程有問(wèn)題。
public long longValue(); //等價(jià)與sum();
LongAccumulator(JDK8)
LongAdder 類是 LongAccumulator 的一個(gè)特例,LongAccumulator 更加強(qiáng)大。
構(gòu)造方法:
//當(dāng) function 為null時(shí),雙目運(yùn)算器為默認(rèn)的加法運(yùn)算器
public LongAccumulator(LongBinaryOperator function, long identify){
this.function = function;
base = this.identify = identify;//可以提供非0的初始值
}
//LongBinaryOperator雙目運(yùn)算器接口
public interface LongBinaryOperator{
long applyAsLong(long left, long right);
}