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

 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实现

  • 13
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值