Java併發編程之CAS第一篇-什麼是CASjava
經過前面幾篇的學習,咱們對併發編程兩個高頻知識點了解了其中的一個—volatitl。從這一篇文章開始,咱們將要學習另外一個知識點—CAS.本篇是《凱哥併發編程學習》系列之《CAS系列》教程的第一篇:什麼是CAS。算法
本文主要內容:數據庫
生活中舉例;CAS定義;CAS代碼演示。編程
在電影《智取威虎山》中,楊子榮進入威虎山的時候,土匪說:天王蓋地虎,楊子榮對:寶塔鎮河妖。相似這樣的黑話,幾個土匪和楊子榮對過以後,座山雕,三爺才發話:這麼說,你是徐旅長的人了。相信電影中這段對黑話,你們都看過。有沒有感受很過癮呢?那麼問題來了,爲何幾我的對過黑話以後,就能肯定來者身份呢?由於在那個時候,佔山爲王,各個山頭都有老大,可是又要和其餘山頭交流,不能用明話來講。因而你們就編了一些黑話。根據黑話不一樣,來確認對方的身份。多線程
這個過程若是站在計算機多線程併發編程角度來理解的話,能夠這麼來理解。黑話庫就是主內存中變量楊子榮和其餘土F是不一樣的線程。,他們之間的黑話就是各自從主內存複製的變量副本。當T匪A(也就是線程A):天王蓋地虎是本身的副本的數據,想要更新爲:寶塔鎮河妖。當楊子榮回答後,T匪A就拿着,天王蓋地虎,寶塔鎮河妖,這句話和黑話庫(主內存)對比,對比上,則說明楊子榮說的對。容許接下來對話。若是這個很差理解的話,咱們在舉個例子。併發
修改登錄密碼,這個你們都操做過吧。不管是各個APP仍是各地網站都支持修改密碼。那麼修改密碼的三要素是什麼你們知道嗎:數據庫存儲的原祕密;用戶輸入的原祕密;以及將要更新的密碼。數據存儲的原祕密(主內存),用戶輸入的原祕密(線程副本)。當數據庫中存儲的和用戶輸入的原密碼對比相同的時候,才能夠將原密碼更新爲新密碼。不然就不能更新。ide
從上面兩個例子咱們能夠看到,要想成功,須要三個變量:主內存變量值、線程本身工做區副本值以及要更新的數據值。若是有了上面三個概念,咱們就來看看什麼是CAS性能
CAS:Compare and Swap 三個字母的縮寫。學習
是什麼意思呢?Compare:比較 Swap:交換。因此CAS即爲:比較並交換的意思。網站
須要注意:and 是並的意思。在邏輯運算中,並的意思:只有都成立了才能夠執行下面操做。
那麼在Java併發中爲何會大量的使用到CAS呢?
那是由於CAS是無鎖的一種算法。爲了解決多線程並行(併發)狀況下使用鎖的話,性能消耗的一種機制。
CAS操做包含了三個操做數據。分別是:主內存數據值或主內存位置(V)、線程工做區副本更新前的數據值或者是預期值(A)以及要更新成的新值(B)。
操做流程:
線程M在更新的共享變量的時候,會拿着本身工做區變量副本A的值,假設是1,將要更新的值B。假設是2.去更新主內存共享變量V的時候,會先拿着V和A比較。若是V==A的時候,纔會將主內存V的值換成B。不然就會從新獲取主內存的值,進行自旋操做,知道成功位置。
簡單理解:我(線程M,工做區值爲A)認爲主內存V中的共享變量值是(包含)A,若是 V的值是A,那麼就將B替換V。若是不是,就不更新V的值,只要告訴我V的最新值。我本身自旋操做,本身玩。
咱們知道在JUC下,有個原子包,就在atomic包下,咱們用來演示CAS代碼就用AtomicInteger這個類來演示。代碼以下圖:
問題:
在12和13行,運行後的結果是什麼呢?
true 運行後。當前i的值爲:2020
false 運行後。當前i的值爲:2020
爲何會是這樣呢?
咱們來分析:
在11行的時候,聲明瞭變量i.並賦值爲1(即V),而後第12行,拿着預期值1(即A),和將要更新的值2020(即B).進行CAS以後,由於1==1也就是V==A。這個中狀況下,就會把2020從新賦值給V。因此,第12行輸出的就是true和2020;
在第13行假設是線程2來訪問。線程2本身工做空間變量副本依然是1,更行值是1024.這個時候進行CAS的時候,由於如今主內存V的值是2020,因此2020 != 1也就是V != A。這個時候,V的值不能被更新,因此第13行輸出的是就是false和2020.
在看下面:
問題:第14行輸出的是什麼呢 ?
咱們來看看運行結果:
爲何呢?你們能夠嘗試這去分析分析。(PS:提示,看看上文CAS定義和CAS操做流程來分析)。
在下一節中,凱哥(凱哥Java:kaigejava)將和你們嘮嘮CAS的原理。爲何,若是不加鎖的話,volatile不能保證原子性,可是atomic包下的類就能夠保證原子性呢?咱們從AtomicInteger源碼追根溯源吧。