一、CAS機制
1.CAS(Compare-and-Swap),即比較並替換,java並發包中許多Atomic的類的底層原理都是CAS。
2.CAS需要有3個操作數:
1)需要讀寫的內存值 V
2)進行比較的預期值 A
3)擬寫入的新值 B。
CAS指令執行時,當且僅當內存值V與預期值A相等時,將內存值V修改為B,否則就什么都不做。
整個比較並替換的操作是一個原子操作。
3.CAS是樂觀鎖的一種實現方式。
二、CAS的缺點
CAS雖然很高效的解決了原子操作問題,但是CAS仍然存在三大問題。
1) CPU開銷大。
2) 不能保證代碼塊的原子性,只能保證一個共享變量的原子操作。
3)ABA問題。
三、自旋鎖:循環
自旋鎖:自旋鎖就是讓不滿足條件的線程循環等待,而不是立即掛起。
通過占用處理器(CPU)的時間來避免線程切換帶來的開銷。
三、悲觀鎖和樂觀鎖
1.悲觀鎖:總是假設最壞的情況,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖。
傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。
再比如Java里面的同步原語synchronized關鍵字的實現就是悲觀鎖,volatile關鍵字雖然是synchronized關鍵字的輕量級實現,但是其無法保證原子性,所以一般也要搭配鎖使用。
2.樂觀鎖:顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。
樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,像數據庫提供的類似於write_condition機制,其實都是提供的樂觀鎖。
在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現方式CAS實現的。
總結:樂觀鎖和悲觀鎖的區別在於拿數據的時候是否認為別人會不會修改,樂觀鎖認為別人不會修改,所以拿數據的時候沒有上鎖。悲觀鎖則認為別人會修改,所以直接上鎖。