JUC-原子類(AtomicInteger)
阿新 • • 發佈:2018-12-14
引入:
我們都知道i++在java中不是原子操作,因為i++的操作實際上分為三個步驟“讀-改-寫”,
int i =10;
i = i++;
實際上是分為下面幾步:
int temp = i;
i = i + 1;
i = temp;
反編譯後可以看到每條指令都會產生一個get和put,它們之間還有一些其他的指令。因此在獲取和放置之間,另一個任務可能會修改這個域,所以這些操作不是原子性的。
JavaSE5引入了諸如AtomicInteger、AtomicLong、AtomicReference等特殊的原子性變數類,可以實現原子操作。它們提供下面形式的原子性條件更新操作:
boolean compareAndSet(expectedValue,updateValue);
這個被稱作CAS(Compare-And-Swap) :比較並交換,該演算法是硬體對於併發操作的支援。
CAS包含了三個運算元:
①記憶體值 V
②預估值 A
③更新值 B
當前僅當V == A時,V = B,否則不會執行任何操作。
模擬CAS演算法:
package com.tongtong.app5; /** *模擬CAS演算法 */ public class TestCompareAndSwap { public static void main(String[] args) { final CompareAndSwap cas = new CompareAndSwap(); for(int i = 0;i < 10; i++){ new Thread(new Runnable() { @Override public void run() { int expectedValue = cas.get(); boolean b = cas.compareAndSet(expectedValue,(int)(Math.random()*101)); System.out.println(b); } }).start(); } } } class CompareAndSwap{ private int value; //獲取記憶體值 public synchronized int get(){ return value; } //比較 public synchronized int compareAndSwap(int expectValue,int newValue){ int oldValue = value; if(oldValue == expectValue){ this.value = newValue; } return oldValue; } //設定 public synchronized boolean compareAndSet(int expectValue,int newValue){ return expectValue == compareAndSwap(expectValue,newValue); } }
原子類操作:
package com.tongtong.app6; import java.util.concurrent.atomic.AtomicInteger; public class TestAtomicDemo { public static void main(String[] args) { AtomicDemo ad = new AtomicDemo(); for(int i = 0;i < 10; i++){ new Thread(ad).start(); } } } class AtomicDemo implements Runnable{ private AtomicInteger serialNumber = new AtomicInteger(0); @Override public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getSerialNumber()); } public int getSerialNumber(){ return serialNumber.getAndIncrement(); //加1,相當於i++ } }