-git
一、關於多線程競爭鎖方面,你們都知道有個CAS和AQS,也正是這兩個東西才引伸出了大量的線程安全類,鎖類等功能; 二、而隨着如今的硬件廠商愈來愈高級,在硬件層面提供大量併發原語給咱們Java層面的開發帶來了莫大的利好; 三、本章節就和你們分享分析一下CAS的工做原理;
一、CAS,compare and swap的縮寫,顧名思義,比較再交換,即 「讀取-修改-寫操做」 三個步驟爲一體原子操做; 二、CAS操做包含三個參數:內存位置(V)、預期值(A)、新值(B); 若是內存位置的值V與預期值A相匹配,那麼處理器會自動將該位置值更新爲新值B,不然不更新;
一、CAS經過JNI方式調用底層操做系統的C代碼,從而藉助底層C代碼來調用CPU底層操做指令來實現原子操做; 二、CAS是硬件CPU提供的原語,經過底層cmpxchg原語指令(多處理器再加上Lock指令)實現原子操做;
一、CAS核心源碼: // Adding a lock prefix to an instruction on MP machine // VC++ doesn't like the lock prefix to be on a single line // so we can't insert a label after the lock prefix. // By emitting a lock prefix, we can define a label after it. #define LOCK_IF_MP(mp) __asm cmp mp, 0 \ __asm je L0 \ __asm _emit 0xF0 \ __asm L0: inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { // alternative for InterlockedCompareExchange int mp = os::is_MP(); __asm { mov edx, dest mov ecx, exchange_value mov eax, compare_value LOCK_IF_MP(mp) // 若是是多處理器的話,則須要添加Lock前綴指令,Lock的方式和Volatile的實現方式雷同 cmpxchg dword ptr [edx], ecx // } } 二、經過上述源碼能夠發現該cmpxchg方法會自動判斷當前是不是多處理器,多處理器的話則添加lock前綴指令,反之省略lock前綴; 三、至於lock是怎麼保證多處理器的一致性的話,原理和Volatile雷同,請移步看看[原理剖析(第 001 篇)Volatile工做原理分析];
一、併發操做時,容易引發ABA問題; 假設i初始值i=5,A線程作i++操做一次,B線程作i--操做一次,C線程經過判斷i=5時則對i進行更新新值; 二、這個時候C線程會認爲i仍是處於初始值,未被作過修改,可是卻不知AB線程已經都對i進行修改了一次; 三、爲了解決這種線程,須要讓C知道i已經被修改過了,所以在Java1.5引進了一個AtomicStampedReference類來解決ABA問題; 四、AtomicStampedReference這個類主要是給變量追加了版本號信息,每次變量更新的話版本號都會自增長一; 五、可是有的人會認爲AtomicMarkableReference也能解決ABA問題,其實不能根本解決只能在最大程度上下降ABA問題的出現; 由於它是經過一個boolean來標記是否更改,本質就是隻有true和false兩種版原本回切換,只能下降ABA問題發生的概率,並不能阻止ABA問題的發生;
一、隨便拿個CAS的Java層代碼: public final int getAndSetInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var4)); return var5; } 二、經過這段代碼發現,若是CAS操做一直不成功的話,那麼該段代碼就一直在自旋操做,會給CPU帶來比較大的執行開銷;
一、目前的CAS只能保證單個共享變量的原子操做; 二、可是對多個變量進行操做時,CAS沒法保證,可是能夠將多個變量封裝成一個新的對象,利用AtomicReference類來保證引用對象之間的原子性;
一、咱們能夠在一些很是簡單的操做且又不想引入鎖的場景下采用CAS實現原子操做; 二、然而想要進行非阻塞的完成某些場景也能夠考慮採用CAS進行原子操做; 三、可是不推薦在很是複雜的操做中引入CAS,一來會使程序可讀性變差,二來且難以測試且會出現ABA問題。
https://gitee.com/ylimhhmily/SpringCloudTutorial.git安全
SpringCloudTutorial交流QQ羣: 235322432微信
SpringCloudTutorial交流微信羣: 微信溝通羣二維碼圖片連接多線程
歡迎關注,您的確定是對我最大的支持!!!併發