首页 > 编程知识 正文

cas aba解决办法,CAS的ABA问题

时间:2023-05-03 12:36:51 阅读:186791 作者:3433

提取java锁在同时执行中占有重要地位,但是一个缺点是线程在没有取得锁的时候被封锁并挂起,为了在锁被释放之前竞争锁而再次唤醒是消耗系统资源的。

由于java线程映射到操作系统的本机线程,因此阻塞或唤醒线程需要操作系统的干预,并且必须在用户状态和核心状态之间切换。 由于该切换在用户状态和内核状态中分别具有专用存储器区域、专用寄存器等,所以从用户状态切换到内核状态需要将很多变量、参数传递给内核,内核根据用户状态切换时的寄存器值、内核

因此,使用无锁定(乐观锁定思想)将大大避免上述问题。 例如,使用volatile定义变量,但volattile只能保证变量的可见性,无法解决读取和重写等原子问题。 在这种情况下,请使用CAS(Compare and Swap)

CAS(compareandswap ) CAS是JDK提供的非阻塞原子操作,JDK中的Unsaf类提供了compareAndSwap*方法。 这些方法都是native方法,也可以说是使用JNI访问本地c实现库,JDK通过硬件访问

运行原理CAS(v,a,b )主要有三个参数,v是内存的值,a是期望值,b是新的值。 如果内存中的值等于预期值,则将内存中的值更新为新值b。 如果内存值不等于预期值,则表示其他线程已将其由其他线程更新。 此时,处理器什么都不做。

如上所述,

对于多线程,一个线程确定V=A成立,然后将v修改为新值。 其他线程的期望值也是修改前的内存值。 此时,判断V=A不成立,将内存中的值重新读入期望值,尝试再次修正v的值。 也就是说,继续CAS。 当然,CAS并不能一直循环,但这样即使时间变长,也会非常消耗CPU资源。

应用CAS操作采用乐观锁定的思想,始终认为自己能够成功操作。 如果多个线程同时使用CAS操作一个变量,则只有一个线程获胜,更新成功,其馀线程失败。 失败的线程不会被挂起,只会通知失败,并允许重试。 当然,也允许失败的线程放弃操作。 基于这种原理,即使CAS操作未被锁定,也可以发现其他线程对当前线程的干扰,并采取适当的操作。

JDK的JUC包(java.util.concurrent.atomic )提供了一组原子类。 常见的是

AtomicInteger :整形原子系atomiclong:long型原子系AtomicBoolean :布尔型原子系AtomicReference :参照型原子系这些原子系的基本特性是,在多线程环境下,多个线程同时这些类其内部是基于CAS算法实现的。 这意味着当一个线程进入方法并执行其中的指令时,它不会被其他线程中断。而别的线程就像自旋锁一样,一直等到该方法执行完成才由JVM从等待的队列中选择另一个线程进入

CAS的ABA问题线程1使用CAS变更初始值1的变量时,首先取得当前变量的值,使用CAS操作试图将变量变更为b,但执行前线程1失去了CPU使用权,线程2进来将变量变更为b,然后使用CAS

例如,在程序逻辑中,当余额还剩100时为帐户充值200,A线程首先获取余额100,然后准备执行200项操作。 那时,线程b来了加200余额,那时余额为300,之后,用户马上消费200,那时余额为100,现在a终于拿到CPU时间段,运行CAS发现余额还在

如何解决ABA的问题通过版本号来解决。 每次进行数据修改操作时都要带上版本号,如果预计上午版本号和内存中的版本号相同,则进行修改操作,不操作版本号1。 因为我觉得版本号是递增的,所以不会发生ABA的问题。 示例: java原子类的AtomicStampedReference和AtomicMarkableReference。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。