【面試普通人VS高手系列】能談一下CAS機制嗎?

跟著Mic學架構發表於2022-04-21

一個小夥伴私信我,他說遇到了一個關於CAS機制的問題,他以為面試官問的是CAS實現單點登入。

心想,這個問題我熟啊,然後就按照單點登入的思路去回答,結果面試官一直搖頭。

他來和我說,到了面試結束都沒明想白自己回答這麼好,怎麼就沒有當場給我發offer呢?

實際上,面試官問的是併發程式設計中的CAS機制。

下面我們來看看普通人和高手對於CAS機制的回答吧

普通人:

CAS,是併發程式設計中用來實現原子性功能的一種操作,嗯,它類似於一種樂觀鎖的機制,可以保證併發情況下對共享變數的值的更改的原子性。

嗯, 像AtomicInteger這個類中,就用到了CAS機制。嗯…

高手:

CAS是Java中Unsafe類裡面的方法,它的全稱是CompareAndSwap,比較並交換的意思。它的主要功能是能夠保證在多執行緒環境下,對於共享變數的修改的原子性。

我來舉個例子,比如說有這樣一個場景,有一個成員變數state,預設值是0,
carbon20220318001

定義了一個方法doSomething(),這個方法的邏輯是,判斷state是否為0 ,如果為0,就修改成1。

這個邏輯看起來沒有任何問題,但是在多執行緒環境下,會存在原子性的問題,因為這裡是一個典型的,Read - Write的操作。

一般情況下,我們會在doSomething()這個方法上加同步鎖來解決原子性問題。

但是,加同步鎖,會帶來效能上的損耗,所以,對於這類場景,我們就可以使用CAS機制來進行優化

這個是優化之後的程式碼
carbon20220318002

在doSomething()方法中,我們呼叫了unsafe類中的compareAndSwapInt()方法來達到同樣的目的,這個方法有四個引數,

分別是:當前物件例項、成員變數state在記憶體地址中的偏移量、預期值0、期望更改之後的值1。

CAS機制會比較state記憶體地址偏移量對應的值和傳入的預期值0是否相等,如果相等,就直接修改記憶體地址中state的值為1.

否則,返回false,表示修改失敗,而這個過程是原子的,不會存線上程安全問題。

CompareAndSwap是一個native方法,實際上它最終還是會面臨同樣的問題,就是先從記憶體地址中讀取state的值,然後去比較,最後再修改。

這個過程不管是在什麼層面上實現,都會存在原子性問題。

所以呢,CompareAndSwap的底層實現中,在多核CPU環境下,會增加一個Lock指令對快取或者匯流排加鎖,從而保證比較並替換這兩個指令的原子性。

CAS主要用在併發場景中,比較典型的使用場景有兩個。

  1. 第一個是J.U.C裡面Atomic的原子實現,比如AtomicInteger,AtomicLong。
  2. 第二個是實現多執行緒對共享資源競爭的互斥性質,比如在AQS、ConcurrentHashMap、ConcurrentLinkedQueue等都有用到。

以上就是我對這個問題的理解。

總結

最近大家也發現了我的文章內容在高手回答部分的變化。

有些小夥伴說,你面試怎麼還能帶圖來,明顯作弊啊。

其實主要是最近很多的面試題都偏底層,而底層的內容涵蓋的知識面比較廣,大家平時幾乎沒有接觸過。

所以,如果我想要去把這些知識傳遞給大家,就得做很多的圖形和內容結構的設計,否則大家看完之後還是一臉懵逼。

好的,本期的普通人VS高手面試系列就到這裡結束了,喜歡的朋友記得點贊收藏。

我是Mic,一個工作了14年的Java程式設計師,我們們下期再見。
file

版權宣告:本部落格所有文章除特別宣告外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Mic帶你學架構
如果本篇文章對您有幫助,還請幫忙點個關注和贊,您的堅持是我不斷創作的動力。歡迎關注同名微信公眾號獲取更多技術乾貨!

相關文章