多執行緒1:AtomicInteger的使用,多執行緒疊加或疊減
阿新 • • 發佈:2019-02-15
- import java.util.concurrent.atomic.AtomicInteger;
- publicclass AtomicIntegerTest {
- public AtomicInteger inc = new AtomicInteger();
- publicvoid increase() {
- inc.getAndIncrement();//i++操作
- //inc.getAndDecrement();//i--操作
- }
- publicstaticvoid main(String[] args) {
-
final
- for (int i = 0; i < 10; i++) {
- new Thread() {
- publicvoid run() {
- for (int j = 0; j < 1000; j++)
- test.increase();
- };
-
}.start();
- }
- while (Thread.activeCount() > 1)
- // 保證前面的執行緒都執行完
- Thread.yield();
- System.out.println(test.inc);
- }
- }
可以發現結果都是10000,也就是說AtomicInteger是執行緒安全的。
值得一看。
這裡,我們來看看AtomicInteger是如何使用非阻塞演算法來實現併發控制的。
AtomicInteger的關鍵域只有一下3個:
-
// setup to use Unsafe.compareAndSwapInt for updates
- privatestaticfinal Unsafe unsafe = Unsafe.getUnsafe();
- privatestaticfinallong valueOffset;
- privatevolatileint value;
這裡, unsafe是Java提供的獲得對物件記憶體地址訪問的類,註釋已經清楚的寫出了,它的作用就是在更新操作時提供“比較並替換”的作用。實際上就是AtomicInteger中的一個工具。
valueOffset是用來記錄value本身在記憶體的便宜地址的,這個記錄,也主要是為了在更新操作在記憶體中找到value的位置,方便比較。
注意:value是用來儲存整數的時間變數,這裡被宣告為volatile,就是為了保證在更新操作時,當前執行緒可以拿到value最新的值(併發環境下,value可能已經被其他執行緒更新了)。
這裡,我們以自增的程式碼為例,可以看到這個併發控制的核心演算法:
- /**
- * Atomically increments by one the current value.
- *
- * @return the updated value
- */
- publicfinalint incrementAndGet() {
- for (;;) {
- //這裡可以拿到value的最新值
- int current = get();
- int next = current + 1;
- if (compareAndSet(current, next))
- return next;
- }
- }
- publicfinalboolean compareAndSet(int expect, int update) {
- //使用unsafe的native方法,實現高效的硬體級別CAS
- return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
- }
好了,看到這個程式碼,基本上就看到這個類的核心了。相對來說,其實這個類還是比較簡單的。可以參考http://hittyt.iteye.com/blog/1130990