最近再读码出高效这本书,在多线并发部分这里多次看到CAS这个词,尤其是在看对ConcurrentHashMap的源码解读中多次提到了。本小节先来学习一下
定义
CAS(Compare And Swap)比较并交换,它是解决轻微冲突的多线程并发场景下使用锁造成性能损耗的一种机制
CAS 算法
CAS包含了3个操作数-需要读写的内存位置V、进行比较的值A和拟写入的新值B,当且仅当V的值等于A时,CAS才会通过原子的方式用新值B来更新V的值,否则不会执行任何操作
🔥🔥如果内存位置的值与预期原值相等,则处理器将该位置的值更新为新值,如果不相等则获取当前值,然后进行不断的轮询操作直到成功或达到某个阈值退出
CAS的典型使用模式
可参照:java并发编程实战264页
JVM 就是利用CAS 在对象头上设置线程 ID, 表示这个对象偏向于当前线程, 这就是偏向锁。
💡💡 CAS这种不加锁而实现操作原子化的并发编程方式在ConcurrentHashMap和线程池中都有涉及
CAS存在的问题
CAS虽然很高效的解决原子操作,但是CAS仍然存在三大问题。ABA问题,循环时间长开销大和只能保证一个共享变量的原子操作
问题
ConcurrentHashMap 怎么保证线程安全?
JDK 1.8 以前通过分段锁,JDK 1.8 以后通过 CAS + Synchronized
JKD8中的 ConcurrentHashMap 避免了锁的使用。虽然源码过程看起来非常复杂,但是思路 却很清晰。
- 当并发量较小时, 优先使用 CAS 的方式直接更新 baseCount 。
- 当更新 baseCount 冲突,则会认为进入到比较激烈的竞争状态, 通过启用
counterCells 减少竞争, 通过 CAS 的方式把总数更新情况记录counterCells对应的位置上
评论区