1、CAS(無鎖的執行者)java
CAS包含3個參數:內存值 V 舊的預期值 A 新值 B算法
當且僅當V值等於A值時,將V的值改成B值,若是V值和A值不一樣,說明已經有其餘線程作了更新,則當前線程什麼都不作,最後返回當前V的真實值。CAS操做是抱着樂觀的態度進行的(樂觀鎖),它老是認爲本身能夠成功地完成操做。多線程
當多個線程同時使用CAS操做一個變量時,只有一個會勝出併成功更新,其他均會失敗;但失敗的線程並不會掛起,僅是被告知失敗,而且容許再次嘗試,也容許失敗的線程放棄操做。基於這樣的原理,CAS操做即便沒有鎖,一樣知道其餘線程對共享資源操做的影響,並執行相應的處理措施。性能
因爲是無鎖操做,所以不可能出現死鎖狀況。this
CAS是一條CPU的原子指令,不會形成所謂的數據不一致問題。atom
2、ABA問題spa
CAS會致使「ABA問題」。CAS算法實現一個重要前提須要取出內存中某時刻的數據,而在下時刻比較並替換,那麼在這個時間差中可能致使數據發生變化。線程
好比一個線程one從內存位置V中取出A,這是另外一個線程two也從內存中取出A,而且two進行了一些操做變成了B,而後two又將V位置的數據變成A,這時候線程one進行CAS操做發現內存中仍然是A,而後one操做成功。儘管線程one的CAS操做成功,可是不表明這個過程就是沒有問題的。code
部分樂觀鎖的實現是經過版本號(version)的方式來解決ABA問題,樂觀鎖每次在執行數據的修改操做時,都會帶上一個版本號, 一旦版本號和數據的版本號一致就能夠執行修改操做並對版本號執行+1操做,不然就執行失敗。由於每次操做的版本號都會隨之增長,因此不會出現ABA問題,由於版本號只會增長不會減小。blog
3、原子包 java.util.concurrent.atomic
JDK1.5的原子包:java.util.concurrent.atomic這個包裏面提供了一組原子類。其基本特性是:在多線程環境下,當有多個線程同時執行這些類實例包含的方法時,具備排他性,即當某個線程進入方法,執行其中的指令時,不會被其餘線程打斷,而別的線程就像自旋鎖同樣,一直等到該方法執行完成,才由JVM從等待隊列中選擇另外一個線程進入。相對於synchronized這種阻塞算法,CAS是非阻塞算法的一種常見實現。因爲通常CPU切換時間比CPU指令集操做更加長,因此JUC在性能上有了很大的提高。以下代碼:
1 public class AtomicInteger extends Number implements java.io.Serializable { 2 private volatile int value; 3 public final int get() { 4 return value; 5 } 6 public final int getAndIncrement() { 7 for (;;) { //CAS 自旋,一直嘗試,直達成功
8 int current = get(); 9 int next = current + 1; 10 if (compareAndSet(current, next)) 11 return current; 12 } 13 } 14 public final boolean compareAndSet(int expect, int update) { 15 return unsafe.compareAndSwapInt(this, valueOffset, expect, update); 16 } 17 }
getAndIncrement採用了CAS操做,每次從內存中讀取數據而後將此數據和+1後的結果進行CAS操做,若是成功就返回結果,不然重試直到成功爲止。而compareAndSet利用JNI來完成CPU指令的操做。