并发编程(三)原子操作CAS
1.CAS(Compare And Swap)原子操作:
假定有兩個操作A和B,如果從執行A的線程來看,當另一個線程執行B時,要么將B全部執行完,要么完全不執行B,那么A和B對彼此來說是原子的。
通過鎖,鎖機制可以實現原子操作,但鎖一般是阻塞的如synchronize關鍵字就是基于阻塞的鎖機制,當一個線程擁有鎖時,訪問同一資源的其他線程就需要等待,直到該線程釋放鎖。
但鎖操作有著諸多的問題,如被阻塞的線程有限度比較高;獲取鎖的線程出現不釋放情況;大量線程競爭鎖,CPU會花費大量的時間和資源進行處理,此外鎖機制是一種比較粗粒度的機制,對于像計數器這樣的需求顯得過于笨重。
實現原子操作還可以通過現代處理器基本都支持的CAS()指令來完成。每一個CAS操作過程都包含三個運算符:一個內存地址V,一個期望的值A和一個新值B,操作的時候如果這個地址上存放的值等于這個期望的值A,則將地址上的值賦為新值B,否則不做任何操作。
CAS的基本思路就是,如果這個地址上的值和期望的值相等,則給其賦予新值,否則不做任何事兒,但是要返回原值是多少。循環CAS就是在一個循環里不斷的做cas操作,直到成功為止。
2.CAS實現原子操作的三大問題
2.1 ABA問題
因為CAS需要在操作值的時候,檢查值有沒有發生變化,如果沒有發生變化則更新,但是如果一個值原來是A,變成了B,又變成了A,那么使用CAS進行檢查時會發現它的值沒有發生變化,但是實際上卻變化了。
ABA問題的解決思路就是使用版本號。在變量前面追加上版本號,每次變量更新的時候把版本號加1,那么A→B→A就會變成1A→2B→3A。
2.2 循環時間長開銷大
自旋CAS如果長時間不成功,就會給CPU帶來很大的執行開銷。
2.3 只能保證一個共享變量的原子操作
當對一個共享變量執行操作時,我們可以使用循環CAS的方式來保證原子操作,但是對多個共享變量操作時,循環CAS就無法保證操作的原子性,這個時候就可以用鎖。
還有一個取巧的辦法,就是把多個共享變量合并成一個共享變量來操作。比如,有兩個共享變量i=2,j=a,合并一下ij=2a,然后用CAS來操作ij。從Java 1.5開始,JDK提供了AtomicReference類來保證引用對象之間的原子性,就可以把多個變量放在一個對象里來進行CAS操作。
3.原子操作類的使用
AtomicInteger? 原子更新基本類型
compareAndSet():先判斷當前值(舊值)與期望值(expect)是否相等,如果相等 將新值(update)設置為當前值(覆蓋了舊值),
/*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.** @param expect the expected value* @param update the new value* @return {@code true} if successful. False return indicates that* the actual value was not equal to the expected value.*/public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}/**
* Gets the current value.
*
* @return the current value
*/
public final int get() {
return value;
} incrementAndGet() (類比于) --> ++i getAndIncrement() (類比于)--> i++
AtomicIntegerArray 原子更新數組里的整形
原子更新引用類型:
AtomicReference
AtomicStampedReference 利用版本戳的形式記錄每次改變后的版本號,解決ABA問題, pair使用?int stamp作為計數器使用
AtomicMarkableReference 原子更新帶有標記為的引用類型 pair使用boolean mark.關注是否被動過。
?
參考:http://enjoy.ke.qq.com
轉載于:https://www.cnblogs.com/cangshublogs/p/10763844.html
總結
以上是生活随笔為你收集整理的并发编程(三)原子操作CAS的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pcie的ack/nak机制
- 下一篇: domain logic approac