CAS和鎖的相關面試題
- 2020 年 8 月 20 日
- 筆記
CAS 鎖
鎖的四種狀態和升級
鎖的四種狀態:無鎖、偏向鎖、輕量級鎖和重量級鎖
無鎖
無鎖就是沒有真正意義上的上鎖,所有的線程還是能訪問並修改同一個資源,但是通過算法控制,實現同時只有一個線程修改成功。CAS原理及應用即是無鎖的實現。無鎖無法全面代替有鎖,但無鎖在某些場合下的性能是非常高的。
比如:
CAS全稱 Compare and Swap(比較與交換),是一種無鎖算法。
在不使用鎖的情況下(沒有線程被阻塞),實現多線程的變量同步。
CAS算法主要涉及到3個操作數:
①需要進行讀寫操作的值 V
②判斷是否更新的比較值 A
③需要替換值V寫入新的值 B
在最開始將V賦值給A,再進行數據操作生成B,需要更新V之前,
比較一下A是否還與V相等,相等說明數據未變化,執行更新操作,
不相等,則更新不能完成。
CAS全稱 Compare and Swap(比較與交換),是一種無鎖算法。
在不使用鎖的情況下(沒有線程被阻塞),實現多線程的變量同步。
CAS算法主要涉及到3個操作數:
①需要進行讀寫操作的值 V
②判斷是否更新的比較值 A
③需要替換值V寫入新的值 B
在最開始將V賦值給A,再進行數據操作生成B,需要更新V之前,
比較一下A是否還與V相等,相等說明數據未變化,執行更新操作,
不相等,則更新不能完成。
偏向鎖
偏向鎖是指一段同步代碼一直只被一個線程所訪問,那麼該線程會自動獲取鎖,降低獲取鎖的成本。
> 例如:家裡只有一個碗,但也只有我一個人需要一個碗吃飯,所以不存在爭搶,這就是偏向鎖
因為在大多數情況下,鎖總都是被同一個線程多次反覆獲得,不存在多線程競爭,所以就出現了偏向鎖。目標就是在只有一個線程執行同步代碼塊時能夠提高性能。
偏向鎖只有遇到其他線程嘗試競爭偏向鎖時,持有偏向鎖的線程才會釋放鎖,線程不會主動釋放偏向鎖。
> 例如:我家還是只有一個碗,當我朋友來我家和我一起吃飯,這時候就有兩個人,只有這一個碗吃飯,偏向鎖升級
偏向鎖的撤銷,需要等待全局安全點(在這個時間點上沒有位元組碼正在執行),它會首先暫停擁有偏向鎖的線程,判斷鎖對象是否處於被鎖定狀態。撤銷偏向鎖後恢復到輕量級鎖(標誌位為「00」)的狀態。 **當進入偏向鎖的時候 先進行線程id判斷,如果是同一個線程,那不會進行鎖的升級,如果線程的id不同那麼會 進行線程的競爭,這時候會進行鎖升級;**
輕量級鎖
是指當鎖是偏向鎖的時候,被另外的線程所訪問,偏向鎖就會升級為輕量級鎖,其他線程會通過自旋的形式嘗試獲取鎖,不會阻塞,從而提高性能。
如果這個更新動作成功了,那麼這個線程就擁有了該對象的鎖,並且對象Mark Word的鎖標誌位設置為「00」,表示此對象處於輕量級鎖定狀態。
如果輕量級鎖的更新操作失敗了,虛擬機首先會檢查對象的Mark Word是否指向當前線程的棧幀,如果是就說明當前線程已經擁有了這個對象的鎖,那就可以直接進入同步塊繼續執行,否則說明多個線程競爭鎖。
若當前只有一個等待線程,則該線程通過自旋進行等待。但是當自旋超過一定的次數,或者一個線程在持有鎖,一個在自旋,又有第三個來訪時,輕量級鎖升級為重量級鎖。
重量級鎖
> 當我和女朋友都很餓的時候,我女朋友覺得我吃的太慢了,不想等我吃完,這時候就會去爭搶這唯一的一個碗先吃飯,這是重量級鎖狀態
升級為重量級鎖時,鎖標誌的狀態值變為「10」,此時Mark Word中存儲的是指向重量級鎖的指針,此時等待鎖的線程都會進入阻塞狀態。
這裡只有如果深入了解 會涉及到 用戶態(輕量級問題)和內核態(重量級問題、操作系統)的問題!!!
## 總結
> 整體的鎖狀態升級流程是:無鎖-> 偏向鎖 -> 輕量級鎖 -> 重量級鎖
鎖狀態的改變是根據競爭激烈程度進行的,在幾乎無競爭的條件下,會使用偏向鎖,在輕度競爭的條件下,會由偏向鎖升級為輕量級鎖, 在重度競爭的情況下,會升級到重量級鎖。
偏向鎖通過對比Mark Word 解決加鎖問題,避免執行CAS操作。
輕量級鎖是通過CAS操作和自旋來解決加鎖問題,避免線程阻塞和喚醒帶來的性能影響。
重量級鎖是將除擁有鎖的線程之外的線程全部阻塞。
那cas是什麼? cas中會遇見哪些問題 如何解決?
cas即比較並替換,是一種實現並發算法時常用到的技術
裏面有三個操作數:內存值V、舊的預期值A、要修改的值B;
當預期值A和內存值V相同時,才會將內存值修改為B並返回true,否則什麼都不做並返回false。
CAS存在ABA問題,解決方案是:可以對每個值添加一個版本號來判斷,CAS只是一種思想
使用CAS+版本號進行解決,對一個數據如果修改了的話,那麼版本號就進行+1,然後再循環比較的時候,不僅僅比較值再根據版本號就可以解決ABA問題。
如果版本號相同我們就可以加入時間戳 當版本號和時間戳都相同時 才會進行數據的改變!