昨天的文章 我們針對 Java 語言的 "happends-before" 原則做了一個非常簡單的表述,以致于有同學提到我這個話語的嚴謹性問題。而這個原則在 Java 語言里面非常重要,以致于我必須重新引用一下相關書籍的話來進行論述。
"happends-before" 先行發(fā)生原則是 Java 內(nèi)存模型中定義的兩項操作之間的偏序關系,如果說操作 A 先行發(fā)生于操作 B,那么操作 A 產(chǎn)生的影響一定應該被操作 B 所觀察到。
而對于我們 volatile
保證的可見性, synchronized
和 final
關鍵字也同樣可以做到。那我們今天就來簡單講一下我們非常常用的 synchronized
和似乎在 Android 中少有聽到的 CAS 機制。
synchronized 和 CAS 的區(qū)別
synchronized
采用的是 CPU 悲觀鎖機制,即線程獲得的是獨占鎖。獨占鎖就意味著 其他線程只能依靠阻塞來等待線程釋放鎖。而在 CPU 轉換線程阻塞時會引起線程上下文切換,當有很多線程競爭鎖的時候,會引起 CPU 頻繁的上下文切換導致效率很低。盡管 Java1.6 為 synchronized
做了優(yōu)化,增加了從偏向鎖到輕量級鎖再到重量級鎖的過度,但是在最終轉變?yōu)橹亓考夋i之后,性能仍然較低。
CAS 是英文單詞 Compare And Swap 的縮寫,翻譯過來就是比較并替換。它當中使用了3個基本操作數(shù):內(nèi)存地址 V,舊的預期值 A,要修改的新值 B。采用的是一種樂觀鎖的機制,它不會阻塞任何線程,所以在效率上,它會比 synchronized
要高。所謂樂觀鎖就是:每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。
所以,在并發(fā)量非常高的情況下,我們盡量的用同步鎖,而在其他情況下,我們可以靈活的采用 CAS 機制。
那些地方采用了 CAS 機制
在 java.util.concurrent.atomic
包下,一系列以 Atomic
開頭的包裝類。例如AtomicBoolean
,AtomicInteger
,AtomicLong
等,它們就是典型的利用 CAS 機制實現(xiàn)的原子操作類。
此外,Lock
系列類的底層實現(xiàn)以及 Java 1.6 在 synchronized
轉換為重量級鎖之前,也會采用到 CAS 機制。
關于 CAS 機制的更多相關信息請移步:
漫畫:什么是CAS機制?(進階篇)