通過上面的小例子,我們可以發現每次計算的結果都是有偏差的。為什麽會有偏差?這是因為JMM將記憶分為工作記憶和主記憶。我們的操作是在工作內存中進行的,然後將獲得的值同步到主內存中。
從上圖中我們可以看到,i=0最初在主存中,此時線程A將I讀入工作內存並開始i++操作,然後將操作結果i=1同步到主存中。但是,由於整個過程不是原子的(在線程A的操作過程中,線程B也可以執行操作),因此在線程A可以將計算的值刷新回主內存之前,線程B開始執行i++操作,並且線程B獲得的I的值是0而不是線程A計算的1,因此線程B在操作後獲得的結果是1,這導致了以下情況。
1 .同步鎖
當我們為i++添加同步鎖時,我們可以確保它是原子性的,從而確保同壹時間只有壹個線程可以對I執行++操作,從而確保線程安全。
通過同步鎖後,結果與預期結果壹致。synchronized的基本原理不是本文的重點,稍後會有壹篇單獨的文章進行分析。
2.通過J.U.C .軟件包下的AtomicInteger。
好了,前面準備了這麽多,現在正式介紹本文的重點:CAS,AtomicInteger是基於CAS技術實現的。
CAS、Compare和Swap被比較和替換。這是實現樂觀鎖定思想的壹種方式。
從圖中我們可以看到CAS的實現原理:CAS有三個操作數:內存值V、舊的預期值A和要修改的值B .當且僅當預期值A和內存值V相同時,將內存值修改為B並返回true,否則不執行任何操作並返回false。
1.點擊getAndIncrement()方法,我們會發現AtomicInteger調用了Unsafe的getAndInt()方法。
小知識:JVM是壹種規範,目前市場上主要有四種實現。
熱點:最常用的jvm實現
2)JRocket:JRocket是BEA公司的JVM。使用WebLogic的用戶經常使用JRocket虛擬機。
3)J9:IBM的JVM。
4)Harmony:由IBM和Intel JVM合作開發的開源JVM。IBM打頭陣,英特爾是主力軍。
找到atomic_linux_x86.inline.hpp並找到cmpxchg方法。
CAS是壹種樂觀鎖定,它使用spin等待其他線程完成工作。在低競爭和短等待時間的任務場景中表現出色。
1)因為CAS采用自旋模式,而自旋占用CPU資源。
2)只能保留壹個變量的原子操作。
3)脫落酸問題
在這裏,我給朋友們解釋壹下ABA是什麽,或者以CAS流程圖為例。
如前所述,盡管CAS會占用CPU資源,但它只能在用戶模式下完成鎖定過程(不涉及內核模式)。那麽線程少、競爭少、等待時間短的場景是CAS的最佳場景。朋友們到了嗎?