JAVA 中無鎖的線程安全整數 AtomicInteger,一個提供原子操做的Integer的類。在Java語言中,++i和i++操做並非線程安全的,在使用的時候,不可避免的會用到synchronized關鍵字。而AtomicInteger則經過一種線程安全的加減操做接口。AtomicInteger爲何可以達到多而不亂,處理高併發應付自如呢?這是由硬件提供原子操做指令實現的,這裏面用到了一種併發技術:CAS。在非激烈競爭的狀況下,開銷更小,速度更快。
Java.util.concurrent中實現的原子操做類包括:java
AtomicBoolean、AtomicInteger、AtomicIntegerArray、AtomicLong、AtomicReference、AtomicReferenceArray。
1.悲觀鎖與樂觀鎖:程序員
- 悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認爲別人會修改,因此每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關係型數據庫裏邊就用到了不少這種鎖機制,好比行鎖,表鎖等,讀鎖,寫鎖等,都是在作操做以前先上鎖。 - 樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認爲別人不會修改,因此不會上鎖,可是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣能夠提升吞吐量,像數據庫若是提供相似於write_condition機制的其實都是提供的樂觀鎖。
兩種鎖各有優缺點,不可認爲一種好於另外一種,像樂觀鎖適用於寫比較少的狀況下,即衝突真的不多發生的時候,這樣能夠省去了鎖的開銷,加大了系統的整個吞吐量。但若是常常產生衝突,上層應用會不斷的進行retry,這樣反卻是下降了性能,因此這種狀況下用悲觀鎖就比較合適。數據庫
2.CAS:安全
CAS就是Compare and Swap的意思,比較並操做。不少的cpu直接支持CAS指令。CAS是項樂觀鎖技術,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程並不會被掛起,而是被告知此次競爭中失敗,並能夠再次嘗試。CAS有3個操做數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改成B,不然什麼都不作。多線程
private static final Unsafe unsafe = Unsafe.getUnsafe();
package AtomicData; import java.util.concurrent.atomic.AtomicInteger; public class Test { public static void main(String[] args) throws InterruptedException { Test test = new Test(); MyThread my = new MyThread(test); for (int i = 0; i < 500; i++) { Thread t = new Thread(my); t.start(); } //等待子線程執行完 Thread.sleep(5000); System.out.println(test.number); } AtomicInteger number = new AtomicInteger(0); protected void update() { number.getAndAdd(1); } } class MyThread implements Runnable { Test t; public MyThread(Test t){ this.t =t; } @Override public void run() { t.update(); } }