java.util.concurrent 是基於Queue 的併發包,而Queue,不少
狀況下使用到了Atomic 操做。一般狀況下,在Java裏面在沒有額外資源能夠利用的狀況下,只能使用加鎖才能保證讀-改-寫這三個操做時「原子」的。則須要使用synchronized和volatile關鍵字,代價很高,還須要jni。java
JDK 5.0後,則重複使用現代cpu特性下降鎖消耗算法
int addAndGet(int delta) //以原子方式將給定值與當前值相加。實際上就是等於線程安全版本的i=i+delta操做。 boolean compareAndSet(int expect, int update)//若是當前值== 預期值,則以原子方式將該值設置爲給定的更新值。若是成功就返回true,不然返回false,而且不修改原值。 int decrementAndGet()//以原子方式將當前值減1。至關於線程安全版本的--i 操做。 int get()//獲取當前值。 int getAndAdd(int delta)//以原子方式將給定值與當前值相加。至關於線程安全版本的t=i;i+=delta;return t;操做。 int getAndDecrement()以原子方式將當前值減1。至關於線程安全版本的i--操做。 int getAndIncrement()//以原子方式將當前值加1。至關於線程安全版本的i++操做。 int getAndSet(int newValue)//以原子方式設置爲給定值, 並返回舊值。至關於線程安全版本的t=i;i=newValue;return t;操做。 int incrementAndGet()//以原子方式將當前值加1。至關於線程安全版本的++i 操做。 ...
AtomicInteger 和AtomicLong、AtomicBoolean、AtomicReference 差很少api
API和AtomicInteger 是相似的,這種經過方法、參數的名稱就可以獲得函數意義的寫法是很是值得稱讚數組
int get(int i)//獲取位置i 的當前值。很顯然, 因爲這個是數組操做, 就有索引越界的問題 void set(int i, int newValue) void lazySet(int i, int newValue) int getAndSet(int i, int newValue) boolean compareAndSet(int i, int expect, int update) boolean weakCompareAndSet(int i, int expect, int update) int getAndIncrement(int i) int getAndDecrement(int i) int getAndAdd(int i, int delta) int incrementAndGet(int i) int decrementAndGet(int i) int addAndGet(int i, int delta)
AtomicIntegerFieldUpdater
約束:安全
只能是實例變量多線程
public class AtomicIntegerFieldUpdaterDemo { class DemoData{ public volatile int value1 = 1; } void main() { DemoData data = new DemoData(); AtomicIntegerFieldUpdater.newUpdater(DemoData.class, value1).getAndSet(data, 10)); } }
Java 語言規範規定了JVM 線程內部維持順序化語義,也就是說只要程序的最終結果等同於
它在嚴格的順序化環境下的結果,那麼指令的執行順序就可能與代碼的順序不一致。這個
過程經過叫作指令的重排序。併發
意義: JVM 可以根據處理器的特性(CPU 的多級緩存系統、多核處理器等)適當的從新排序機器指令,使機器指令更符合CPU 的執行特色,最大限度的發揮機器的性能。app
若是動做B 要看到動做A 的執行結果(不管A/B 是否在同一個線程裏面執行),那麼A/B 就須要知足happens-before 關係。函數
JMM 動做(Java Memeory Model Action),
Java 存儲模型動做。一個動做(Action)包括:變量的讀寫、監視器加鎖和釋放鎖、線程的
start()和join()
volatile 至關於synchronized 的弱實現,也就是說volatile 實現了相似synchronized 的語義,
卻又沒有鎖機制。
儘管volatile 變量的特性不錯,可是volatile 並不能保證線程安全的,也就是說volatile 字段
的操做不是原子性的,volatile 變量只能保證可見性(一個線程修改後其它線程可以理解看
到此變化後的結果),要想保證原子性,目前爲止只能加鎖!
缺點:
若是一個優先級高的線程等待一個優先級低的線程釋放鎖會致使優先級倒置,引發性能風險。
volatile 是不錯的機制,可是volatile 不能保證原子性。所以對於同步最終仍是要回到鎖機制
上來。
獨佔鎖是一種悲觀鎖,synchronized 就是一種獨佔鎖,會致使其它全部須要鎖的線程掛起,
等待持有鎖的線程釋放鎖。而另外一個更加有效的鎖就是樂觀鎖。所謂樂觀鎖就是,每次不加
鎖而是假設沒有衝突而去完成某項操做,若是由於衝突失敗就重試,直到成功爲止。
上面的樂觀鎖用到的機制就是CAS,Compare and Swap。
CAS 有3個操做數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A 和內存
值V 相同時,將內存值V 修改成B,不然什麼都不作。
非阻塞算法(nonblocking algorithms)
一個線程的失敗或者掛起不該該影響其餘線程的失敗或掛起的算法。
public final int incrementAndGet() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return next; } }
總體的過程,利用CPU 的CAS 指令,同時藉助JNI 來完成Java 的非阻塞算法。