在并發程式設計中,自旋鎖(spin locks )想必大家都不陌生。
自旋鎖一個非常經典的使用場景是CAS(即比較和交換),是一種無鎖的思想(說白了就是使用了無限循環),用來解決更新資料的問題高并發場景。
atomic包下的很多類,如AtomicInteger、AtomicLong、AtomicBoolean等,都是用CAS實作的。
我們以AtomicInteger類為例,它incrementAndGet不會每次都給變量加 1。
<b>public</b> <b>final</b> <b>int</b> incrementAndGet() {
<b>return</b> unsafe.getAndAddInt(<b>this</b>, valueOffset, 1) + 1;
}
它的底層是用自旋鎖實作的:
<b>public</b> <b>final</b> <b>int</b> getAndAddInt(Object <b>var</b>1, <b>long</b> <b>var</b>2, <b>int</b> <b>var</b>4) {
<b>int</b> <b>var</b>5;
<b>do</b> {
<b>var</b>5 = <b>this</b>.getIntVolatile(<b>var</b>1, <b>var</b>2);
} <b>while</b>(!<b>this</b>.compareAndSwapInt(<b>var</b>1, <b>var</b>2, <b>var</b>5, <b>var</b>5 + <b>var</b>4));
<b>return</b> <b>var</b>5;
}
在do…while無限循環中,不斷地進行資料的比較和交換。如果一直失敗,就會一直重試。
在高并發的情況下,compareAndSwapInt大機率會失敗,進而導緻CPU不斷自旋,嚴重浪費CPU資源。
那麼,如果這個問題解決了呢?
<b>private</b> <b>boolean</b> compareAndSwapInt2(Object <b>var</b>1, <b>long</b> <b>var</b>2, <b>int</b> <b>var</b>4, <b>int</b> <b>var</b>5) {
<b>if</b>(<b>this</b>.compareAndSwapInt(<b>var</b>1,<b>var</b>2,<b>var</b>4, <b>var</b>5)) {
<b>return</b> <b>true</b>;
} <b>else</b> {
LockSupport.parkNanos(10);
<b>return</b> false;
}
}