Java多線程場景解析volatile和AtomicLong區(qū)別原理
【摘要】
隨著多線程編程的普及,volatile和AtomicLong這兩個關鍵字被越來越多的使用。但是很多人并不理解它們的原理以及區(qū)別。今天我就來通過一個典型的場景,講解 volatile 和 AtomicLong 的用法、原理以及區(qū)別,希望可以幫助大家更好地使用這兩者。
我們假設有這樣一個多線程場景:存在一個長整型變量,多個線程同時進行讀寫操作。為了保證線程安全,我們通常會進行同步,但是同步操作又會影響效率。這個時候我們就可以考慮用 volatile 或者 AtomicLong 來優(yōu)化。
volatile
先說說 volatile,它可以保證變量的可見性,具體來說就是當一個線程修改了 volatile 變量,新值對其他線程立即可見。這是因為volatile變量直接操作主內(nèi)存,而不是線程的工作內(nèi)存。
java public class VolatileExample { volatile long count = 0; public void increment() { count++; } public long getCount() { return count; } }
這里通過 volatile 關鍵字,可以保證多個線程都能讀取到 count 的最新的值。但是,volatile 并不能保證原子性。什么意思呢?我們來看看下面的代碼:
java public void increment() { count++; } // 這里的遞增操作并不是原子的,實際會分為三步 // 1. 讀取count值 // 2. 計算值+1 // 3. 寫入新的值
也就是說某一個時刻,可能有兩個線程同時讀取了 count 值,然后分別增加,這就破壞了原子性。要解決這個問題,我們就需要 AtomicLong 了。
AtomicLong
AtomicLong 通過 CAS (Compare And Swap) 算法實現(xiàn)了對長整型的原子操作??匆粋€例子:
java AtomicLong atomicCount = new AtomicLong(); public void increment() { atomicCount.getAndIncrement(); }
getAndIncrement()會先獲取當前的值,然后原子地增加,最后返回舊值。這樣多個線程調(diào)用的時候可以保證原子性。AtomicLong 的 CAS 原理是通過循環(huán)調(diào)用 CAS 指令,直到更新成功為止:
java do { // 獲取舊的預期值 oldValue = atomicCount.get(); // 用CAS指令更新值,如果預期值一樣才更新 success = compareAndSet(oldValue, oldValue + 1); // 如果失敗,繼續(xù)循環(huán)執(zhí)行CAS } while(!success);
通過 CAS 不斷嘗試更新,直到成功為止。
volatile 和 AtomicLong 的區(qū)別
總結(jié)一下 volatile 和 AtomicLong 的區(qū)別
1. volatile 保證可見性,AtomicLong 保證原子性
2. volatile 不會對代碼產(chǎn)生線程鎖,AtomicLong 會通過 CAS 產(chǎn)生線程開銷
3. volatile 是通過直接操作主內(nèi)存實現(xiàn),AtomicLong 是通過 CAS 實現(xiàn)那么什么時候該用 volatile,什么時候該用 AtomicLong 呢?
- 如果只要保證可見性,那用 volatile 即可。
- 如果需要原子操作,如對數(shù)字進行遞增操作,這時就需要用 AtomicLong。
當然,synchronized和Lock也能保證原子性,但是通過 CAS 實現(xiàn)的 AtomicLong 性能會更好一些。
以上就是本文的全部內(nèi)容了,通過一個典型多線程場景講解了 volatile 和 AtomicLong 的用法、原理以及區(qū)別。這兩個關鍵字非常有用,正確理解后可以充分利用它們帶來的優(yōu)勢,更多關于 Java volatile AtomicLong的資料請關注腳本之家其它相關文章!
相關文章
springboot跨域訪問cros與@CrossOrigin注解詳析
這篇文章主要給大家介紹了關于springboot跨域訪問cros與@CrossOrigin注解的相關資料,跨域是指不同域名之間相互訪問,它是瀏覽器的同源策略造成的,是瀏覽器對JavaScript施加的安全限制,需要的朋友可以參考下2023-12-1210個SpringBoot參數(shù)驗證你需要知道的技巧分享
參數(shù)驗證很重要,是平時開發(fā)環(huán)節(jié)中不可少的一部分,那么在Spring?Boot應用中如何做好參數(shù)校驗工作呢,本文提供了10個小技巧,你知道幾個呢2023-03-03