### CAS
> Compare and Swap 比較再交換
#### 算法理解
> 無鎖算法
> CAS有3個操作數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改為B,否則什么都不做。
#### ABA問題
在多線程場景下`CAS`會出現`ABA`問題,關于ABA問題這里簡單科普下,例如有2個線程同時對同一個值(初始值為A)進行CAS操作,這三個線程如下
1. 線程1,期望值為A,欲更新的值為B
2. 線程2,期望值為A,欲更新的值為B
線程`1`搶先獲得CPU時間片,而線程`2`因為其他原因阻塞了,線程`1`取值與期望的A值比較,發現相等然后將值更新為B,然后這個時候**出現了線程`3`,期望值為B,欲更新的值為A**,線程3取值與期望的值B比較,發現相等則將值更新為A,此時線程`2`從阻塞中恢復,并且獲得了CPU時間片,這時候線程`2`取值與期望的值A比較,發現相等則將值更新為B,雖然線程`2`也完成了操作,但是線程`2`并不知道值已經經過了`A->B->A`的變化過程。
**`ABA`問題帶來的危害**:
小明在提款機,提取了50元,因為提款機問題,有兩個線程,同時把余額從100變為50
線程1(提款機):獲取當前值100,期望更新為50,
線程2(提款機):獲取當前值100,期望更新為50,
線程1成功執行,線程2某種原因block了,這時,某人給小明匯款50
線程3(默認):獲取當前值50,期望更新為100,
這時候線程3成功執行,余額變為100,
線程2從Block中恢復,獲取到的也是100,compare之后,繼續更新余額為50!!!
此時可以看到,實際余額應該為100(100-50+50),但是實際上變為了50(100-50+50-50)這就是ABA問題帶來的成功提交。
[實際線程2是不允許成功的,由于沒有感知到ABA的過程,導致結果執行了]
**解決方法**: 在變量前面加上版本號,每次變量更新的時候變量的**版本號都`+1`**,即`A->B->A`就變成了`1A->2B->3A`。
- 虛擬機
- JVM內存結構
- JVM調優手段
- java對象生命周期
- 垃圾回收判斷對象死亡
- 垃圾回收算法
- 垃圾收集器
- JAVA基礎知識
- java事件機制
- java反射機制
- jvm創建對象
- java異常
- finally語句一定會執行嗎?
- 集合類介紹
- ArrayList
- LinkedList
- HashMap
- ConcurrentHashMap
- 多線程
- 為什么要使用線程池
- 線程死鎖
- 死鎖檢測和解除
- jstack
- jconsole
- 死鎖預防
- 常見線程池
- 線程池參數
- 工作隊列介紹
- 拒絕策略
- ThreadLocal
- CAS
- ReentrantLock
- AQS
- CountDownLatch
- Spring
- spring中bean的作用域
- REDIS
- redis數據結構
- redis hash實現
- redis rehash與hashmap擴容的區別
- Redis使用場景
- Redis為何這么快
- redis連接數不足導致錯誤
- 分布式
- 分布式事務
- ACID
- CAP
- BASE
- 事務隔離性
- 一致性哈希算法
- 負載均衡算法
- Hystrix 信號量和線程池隔離的差異
- Spring Cloud
- eureka
- MYSQL
- mysql優化經驗
- undo redo binlog
- web
- http協議
- http和https區別
- Cookie和session
- TCP三次握手、4次揮手
- TCP的time_wait和close_wait
- 算法問題
- 編輯距離算法
- MQ
- RabbitMq
- Kafka
- 安裝教程
- Win ELK安裝