### 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安装