java多线程(并发)夯实之路-CAS原理与应用深入浅出

发布时间:2024年01月13日

?CAS:保护共享资源的无锁实现

?CAS

CompareAndSet,简称CAS(也有Compare And Swap的说法),它是原子的

它会将pre即之前的值和最新值进行比较,如果相同,修改为next,不同则修改失败??

CAS的底层是lock cmpchg指令(X86架构),在单核和多核CPU下都能保证比较-交换是原子的

使用例子如下:

CAS与volatile

CAS需要volatile支持才能读取到共享变量的最新值实现比较并交换的效果

为什么无锁效率高?

无锁情况下,即使重试失败,线程也在不断运行,而synchronzied会让线程没有锁的时候停止运行,发生上下文切换,进入阻塞(上下文切换成本很高)。

要注意的是,无锁情况下,要保证CPU核心数多于线程数,避免cas线程分不到时间片,发生上下文切换,影响性能

适用场景:CPU核心数多于等于线程数

特点:CAS基于乐观锁的思想,synchronzied基于悲观锁的思想,CAS体现的是无锁并发,无阻塞

并发

CAS应用

原子整数

J.U.C并发包提供了

AtomicBoolean

AtomicInteger

AtomicLong


AtomicInteger方法如下:

updateAndGet原理:用接口的方法具体实现计算结果和cas操作实现

原子引用

原子引用可以使引用类型的变量也能进行cas操作,类型有: AtomicReference

AtomicMarkableReference AtomicStampedReference

AtomicReference例子如下

ABA问题:变量值从A修改为B再修改为A,cas操作仍能够执行成功可以给变量加上一个版本号

AtomicStampedReference(Stamped:时间戳,可以理解为版本号)应用如下

AtomicMarkableReference可以用来判断变量是否被修改过

应用:

原子数组

分为:

AtomicIntegerArray AtomicLongArray AtomicReferenceArray

supplier 提供者 ()-> (一个结果)

function 函数 (一个参数)->(一个结果)?????????????????????????????????????

consumer 消费者 (一个参数)-> ()?

BiFunction (两个参数)-> (一个结果)???????????????????????????????????

BiConsumer(两个参数)-> ()

原子更新器

字段更新器:

AtomicReferenceFieldUpdater AtomicIntegerFieldUpdater AtomicLongFieldUpdater

字段更新器可以针对对象的某个域(Field)进行原子操作,只能配合volatile修饰的字段使用,否则会出现异常

原子累加器

LongAdder,LongAccumulator是专门的累加类

相对于AtomicLong性能更高,因为LongAdder在有竞争时设置多个累加单元(线程1累加Cell[0],线程2累加Cell[1]...最后结果汇总,累加单元不会超过CPU核心数),减少了CAS重试失败的次数。

LongAdder原理

cas锁,不要用于实践,while(true)会一直运行,降低性能

关键的域:

底层实现:Unsafe

Unsafe对象提供了非常底层的,操作内存,线程的方法,unsafe方法不能直接调用,只能通过反射获得

获取:

unsafe通过内存偏移量定位到属性?????

unsafe通过获取到域的偏移地址,再进行cas操作修改值

unsafe模拟实现原子整数

原子整数,原子引用,原子数组,字段更新器,原子累加器底层都是用unsafe实现

文章来源:https://blog.csdn.net/qq_61282807/article/details/135536111
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。