前言
本來想著給自己放鬆一下,刷刷部落格,突然被幾道面試題難倒!執行緒安全需要保證幾個基本特徵?說一下執行緒之間是如何通訊的?CAS的原理呢?CAS有什麼缺點嗎?似乎有點模糊了,那就大概看一下面試題吧。好記性不如爛鍵盤
*** 12萬字的java面試題整理 ***
*** java核心面試知識整理 ***
*** Java高頻面試講解影片(知識涵蓋齊全) ***
執行緒安全需要保證幾個基本特徵?
- 原子性,簡單說就是相關操作不會中途被其他執行緒干擾,一般透過同步機制實現。
- 可見性,是一個執行緒修改了某個共享變數,其狀態能夠立即被其他執行緒知曉,通常被解釋為將執行緒本地狀態反映到主記憶體上,volatile 就是負責保證可見性的。
- 有序性,是保證執行緒內序列語義,避免指令重排等。
說一下執行緒之間是如何通訊的?
執行緒之間的通訊有兩種方式:共享記憶體和訊息傳遞。
共享記憶體
在共享記憶體的併發模型裡,執行緒之間共享程式的公共狀態,執行緒之間透過寫-讀記憶體中的公共狀態來隱式進行通訊。典型的共享記憶體通訊方式,就是透過共享物件進行通訊。
例如上圖執行緒 A 與 執行緒 B 之間如果要通訊的話,那麼就必須經歷下面兩個步驟:
- 執行緒 A 把本地記憶體 A 更新過得共享變數重新整理到主記憶體中去。
- 執行緒 B 到主記憶體中去讀取執行緒 A 之前更新過的共享變數。
訊息傳遞
在訊息傳遞的併發模型裡,執行緒之間沒有公共狀態,執行緒之間必須透過明確的傳送訊息來顯式進行通訊。在 Java 中典型的訊息傳遞方式,就是 wait()
和 notify()
,或者 BlockingQueue
。
CAS的原理呢?
CAS叫做CompareAndSwap,比較並交換,主要是透過處理器的指令來保證操作的原子性,它包含三個運算元:
- 變數記憶體地址,V表示
- 舊的預期值,A表示
- 準備設定的新值,B表示
當執行CAS指令時,只有當V等於A時,才會用B去更新V的值,否則就不會執行更新操作。
CAS有什麼缺點嗎?
CAS的缺點主要有3點:
-
ABA問題:ABA的問題指的是在CAS更新的過程中,當讀取到的值是A,然後準備賦值的時候仍然是A,但是實際上有可能A的值被改成了B,然後又被改回了A,這個CAS更新的漏洞就叫做ABA。只是ABA的問題大部分場景下都不影響併發的最終效果。
Java中有AtomicStampedReference來解決這個問題,他加入了預期標誌和更新後標誌兩個欄位,更新時不光檢查值,還要檢查當前的標誌是否等於預期標誌,全部相等的話才會更新。 -
迴圈時間長開銷大:自旋CAS的方式如果長時間不成功,會給CPU帶來很大的開銷。
-
只能保證一個共享變數的原子操作:只對一個共享變數操作可以保證原子性,但是多個則不行,多個可以透過AtomicReference來處理或者使用鎖synchronized實現。