扫码关注公众号

多线程和并发之CAS和乐观锁
04-07
21观看
01

乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

乐观锁是每次操作时不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。悲观锁是会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。乐观锁可以使用volatile+CAS原语实现,带参数版本来避免ABA问题,在读取和替换的时候进行判定版本是否一致;悲观锁可以使用synchronize以及Lock。

来自:并发和同步-CAS和乐观锁
02

什么是CAS机制?

CAS算法的作用:解决多线程条件下使用锁造成性能损耗问题的算法,保证了原子性,这个原子操作是由CPU来完成的。CAS的原理:CAS算法有三个操作数,通过内存中的值(V)、预期原始值(A)、修改后的新值。(1)如果内存中的值和预期原始值相等,就将修改后的新值保存到内存中。(2)如果内存中的值和预期原始值不相等,说明共享数据已经被修改,放弃已经所做的操作,然后重新执行刚才的操作,直到重试成功。注意:(1)预期原始值(A)是从偏移位置读取到三级缓存中让CPU处理的值,修改后的新值是预期原始值经CPU处理暂时存储在CPU的三级缓存中的值,而内存指定偏移位置中的原始值。(2)比较从指定偏移位置读取到缓存的值与指定内存偏移位置的值是否相等,如果相等则修改指定内存偏移位置的值,这个操作是操作系统底层汇编的一个原子指令实现的,保证了原子性

来自:并发和同步-CAS和乐观锁
03

CAS的缺点是什么?

(1)ABA问题如果一个线程t1正修改共享变量的值A,但还没修改,此时另一个线程t2获取到CPU时间片,将共享变量的值A修改为B,然后又修改为A,此时线程t1检查发现共享变量的值没有发生变化,但是实际上却变化了。解决办法:使用版本号,在变量前面追加上版本号,每次变量更新的时候把版本号加1,那么A-B-A就会变成1A-2B-3A。从Java1.5开始JUC包里提供了一个类AtomicStampedReference来解决ABA问题。AtomicStampedReference类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前版本号是否等于预期版本号,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。(2)循环时间长开销会比较大:自旋重试时间,会给CPU带来非常大的执行开销(3)只能保证一个共享变量的原子操作,不能保证同时对多个变量的原子性操作解决办法:从Java1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行CAS操作

来自:并发和同步-CAS和乐观锁
04

CAS使用时的注意事项有哪些?

(1)CAS需要和volatile配合使用CAS只能保证变量的原子性,不能保证变量的内存可见性。CAS获取共享变量的值时,需要和volatile配合使用,来保证共享变量的可见性(2)CAS适用于并发量不高、多核CPU的情况CPU多核情况下可以同时执行,如果不合适就失败。而并发量过高,会导致自旋重试耗费大量的CPU资源

来自:并发和同步-CAS和乐观锁
专栏
【校招VIP】详解乐观锁的一种实现方式——CAS
csdn
乐观锁
CAS
【校招VIP】面试必备之乐观锁与悲观锁
csdn
面试
乐观锁
悲观锁
【校招VIP】彻底理解Java并发:乐观锁与CAS
csdn
Java并发
乐观锁
CAS
java语言-并发和同步-CAS和乐观锁
3专栏
0课程
4 试题