2015-03-25 20 views
4

此前的Java 8中的AtomicLong類CAS代碼爲:Java 8中AtomicLong類的CAS相關更改如何工作?

public final long incrementAndGet() { 
    for (;;) { 
     long current = get(); 
     long next = current + 1; 
     if (compareAndSet(current, next)) 
      return next; 
    } 
} 

但現在已改爲單內在線:

public final long incrementAndGet() { 
     return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L; 
} 

這段代碼有超過前者有什麼優勢呢?這個新代碼如何工作?

回答

6

原因是循環中的分支預測。在高爭用情況下,CAS循環經常失敗,分支預測器開始預測執行路徑將停留在循環中,當CAS最終成功時會導致大量的管道沖洗。此外,當您真正需要的是CAS失敗時的退避,而不是加速時,這會加速循環。

查看https://blogs.oracle.com/dave/entry/atomic_fetch_and_add_vs瞭解更詳細的治療方法。

+1

感謝您的鏈接。 – 2015-03-29 13:26:53

5

unsafe.getAndAddLong是由JIT翻譯成優化指令序列的JVM內在特性。在x86上,它只是一個單一的CPU指令LOCK XADD

0

正如Jim提供的鏈接中所述,在Java 8中incrementAndGet和其他方法正在利用硬件支持「鎖定,讀取和添加」指令。