併發(2) 原子類
阿新 • • 發佈:2018-12-24
java併發包中提供了一些原子變數類,這些原子變數類提供的方法本身就是一個原子操作。
例如
public class CountingFactorizer implements Servlet{
private final AtomicLong count = new AtomicLong(0);
public void service(ServletRequest req,ServletResponse resp){
count.incrementAndGet();
}
}
上例實現了對訪問的計數,這是一個執行緒安全的類,因為它的計算是一個原子操作。java併發包中還提供了各種型別的原子變數類。
那麼原子變數類是如何實現計算的原子性的呢?
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next; } } public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }
上面的方法中,首現獲取了當前的值,然後對當前值進行加1操作,然後通過unsafe的compareAndSet方法來設定改值。
unsafe的compareAndSet方法做了什麼呢?他首先會去比較當前值是不是預期的值,如果不是返回false,如果是設定新值並返回true。
這種方式也叫做CAS,他不僅是原子類的底層實現方式,也是java鎖的底層實現方式。就是在設定新值之前判斷當前是否還是老值,如果是則設定新值,如果不是則重新計算新值後再嘗試設定。當人CAS實現原子性的基礎是compareAndSet本身是一個原子操作。
原子類
原子類 | 說明 |
AtomicBoolean | boolean原子類 |
AtomicInteger | int原子類 |
AtomicLong | long原子類 |
AtomicReference | 引用原子類 |
AtomicIntegerArray | int原子類陣列 |
AtomicLongArray | long原子類陣列 |
AtomicReferenceArray | 引用原子類陣列 |
AtomicIntegerFieldUpdater | int原子類物件欄位 |
AtomicLongFieldUpdater | long原子類物件欄位 |
AtomicReferenceFieldUpdater | 引用原子類物件欄位 |
AtomicMarkableReference | AtomicReference在使用時會出現aba問題,通過一個識別符號號判斷是否被改過 |
AtomicStampedReference | AtomicReference在使用時會出現aba問題,通過一個int標識是否被改過 |