【JAVA】CAS总结

什么是CAS

CAS的全称为Compare-And-Swap,直译就是对比交换。是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,就是说CAS是靠硬件实现的,JVM只是封装了汇编调用。

简单解释:CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较下在旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。

CAS操作是原子性的,所以多线程并发使用CAS更新数据时,可以不使用锁。

CAS的优缺点

优点:

  1. 由于CAS是非阻塞的,可避免死锁,线程间的互相影响非常小。
  2. 没有锁竞争带来的系统开销,也没有线程间频繁调度的开销。

缺点:

  1. 可能自旋循环时间过长。如果某个线程通过CAS方式操作某个变量不成功,长时间自旋,则会对CPU带来较大开销。怎么解决:限制自旋次数。
  2. 只是一个变量的原子性操作,不能保证代码块的原子性。
  3. ABA问题。

CAS底层原理

  1. java 的 cas 利用的的是 unsafe 这个类提供的 cas 操作。
  2. unsafe 的cas 依赖了的是 jvm 针对不同的操作系统实现的 Atomic::cmpxchg
  3. Atomic::cmpxchg 的实现使用了汇编的 cas 操作,并使用 cpu 硬件提供的 lock信号保证其原子性

CAS 可能会导致什么问题?

CAS存在ABA问题:

  • 当前线程只能感知共享变量的值有没有改变,假设别人从A改成了B,又改成了A,则当前线程感知不到,即ABA问题

  • 可以使用版本号机制解决ABA问题,如原子类AtomicStampedReference,加入了版本号,每当修改值,版本号就会+1

  • 如 AtomicStampedReference 加入了版本号,每当修改值,版本号就会+1。这样根据版本号就知道有没有别的线程修改过,而且还能知道修改过几次

  • 再如 AtomicMarkableReference,他的版本号是一个boolean类型,所以只能判断是否修改过值,不知道修改过几次。

    AtomicMarkableReference只能缓解ABA问题,如果别人修改标记后,又改回来,则无法感知。

CAS 机制可以高效地实现原子操作,但仍不完美:

  1. 循环时间长开销大:CAS 大量失败后长时间占用 CPU 资源,加大了系统性能开销
  2. 只能保证一个共享变量的原子操作:当对一个共享变量执行操作时,我们可以使用循环 CAS 的方式来保证原子操作,但是对多个共享变量操作时,循环 CAS 就无法保证操作的原子性
  3. ABA 问题:CAS 机制本质上依赖值有没有发生变化的操作条件。但是如果值原来是 A、被改成变成了 B、最后又变回了 A,那么使用 CAS 进行检查时会发现它的值没有发生变化进行了操作,但是实际上却变化了,这其实违背了约定的条件。

Java的JUC包里有没有现成的类可以解决CAS的ABA问题?

  • 原子引用:(乐观锁思想) AtomicStampedReference 类可以解决ABA问题。这个类维护了一个【版本号】Stamp,其实有点类似乐观锁的意思。在进行 CAS 操作的时候,不仅要比较当前值,还要比较版本号。只有两者都相等,才执行更新操作。
/**
 * @description: 解决 CAS 带来的 ABA问题
 */
public class ABADemo2 {
	//6为传入的值,1为版本号
    static AtomicStampedReference<Integer> atomic = new AtomicStampedReference<>(6, 1);

    public static void main(String[] args) {

        //使用版本号机制来验证ABA问题
        new Thread(() -> {
            //获取当前版本号
            int stamp = atomic.getStamp();
            System.out.println("线程A1的版本号为:" + stamp);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
			//如果当前引用 等于 预期值并且 当前版本戳等于预期版本戳, 将更新新的引用和新的版本戳到内存
			//compareAndSet(V expectedReference,V newReference,int expectedStamp,int newStamp);
            atomic.compareAndSet(6, 10, atomic.getStamp(), atomic.getStamp() + 1);
            System.out.println("线程A2的版本号为:" + atomic.getStamp());

            System.out.println(atomic.compareAndSet(10, 6, atomic.getStamp(), atomic.getStamp() + 1));
            System.out.println("线程A3的版本号为:" + atomic.getStamp());

        }, "线程A:").start();

        //使用【乐观锁】思想解决ABA问题
        new Thread(() -> {
            int stamp = atomic.getStamp();
            System.out.println("线程B1的版本号为:" + stamp);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(atomic.compareAndSet(6, 2, stamp, stamp + 1));
            System.out.println("线程B2的版本号为:" + atomic.getStamp());

        }, "线程B:").start();
    }
}

  • AtomicStampedReference<>(6, 1); 这两个参数不要填的太大,因为我们本次测试用的是 Integer 类型
  • Integer 使用了对象缓存机制,默认范围是 -128 ~ 127 ,推荐使用静态工厂方法 valueOf 获取对象实例,而不是 new,因为 valueOf 使用缓存,而 new一定会创建新的对象分配新的内存空间。

为什么会导致ABA问题?

这是因为 CAS 算法是在某一时刻取出内存值然后在当前的时刻进行比较,中间存在一个时间差,在这个时间差里就可能会产生 ABA 问题。

Java哪些地方使用了CAS?

Java提供的API中使用CAS的地方有很多,比较典型的使用场景有原子类、AQS、并发容器

  • 对于原子类,以AtomicInteger为例,它的内部提供了诸多原子操作的方法。如原子替换整数值、增加指定的值、加1,这些方法的底层便是采用操作系统提供的CAS原子指令来实现的。
  • 对于AQS,在向同步队列的尾部追加节点时,它首先会以CAS的方式尝试一次,如果失败则进入自旋状态(在队列中自旋),并反复以CAS的方式进行尝试。此外,在以共享方式释放同步状态时,它也是以CAS方式对同步状态进行修改的。
  • 对于并发容器,以ConcurrentHashMap为例,它的内部多次使用了CAS操作。
    • 在初始化数组时,它会以CAS的方式修改初始化状态,避免多个线程同时进行初始化。
    • 在执行put方法初始化头节点时,它会以CAS的方式将初始化好的头节点设置到指定槽的首位,避免多个线程同时设置头节点。在数组扩容时,每个线程会以CAS方式修改任务序列号来争抢扩容任务,避免和其他线程产生冲突。
    • 在执行get方法时,它会以CAS的方式获取头指定槽的头节点,避免其他线程同时对头节点做出修改。

CAS的实现离不开操作系统原子指令的支持,Java中对原子指令封装的方法集中在Unsafe类中,包括:原子替换引用类型、原子替换int型整数、原子替换long型整数。这些方法都有四个参数:var1、var2、var4、var5,其中var1代表要操作的对象,var2代表要替换的成员变量,var4代表期望的值,var5代表更新的值。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: cas client 3.4.1是一个CAS(Central Authentication Service)客户端工具包的版本。CAS是一个单点登录(Single Sign-On)协议,它允许用户通过一次登录即可访问多个应用程序。 CAS client 3.4.1提供了许多功能和特性,使开发人员能够轻松集成CAS协议到他们的应用程序中。这个版本的客户端具有良好的稳定性和兼容性,可与CAS服务器版本3.4.1以及更高版本配合使用。 通过CAS client 3.4.1,应用程序可以使用CAS服务器进行用户认证和授权。它提供了一个简单但强大的API,开发人员可以使用该API创建并处理CAS认证请求。这使得应用程序可以通过CAS单点登录来限制用户的访问。 CAS client 3.4.1的主要功能包括: 1. 用户认证:CAS client可以将用户重定向到CAS服务器以进行认证,并接收并处理CAS服务器传递的认证票据。 2. 单点登出:CAS client允许应用程序执行单点登出操作,以确保用户在一个应用程序注销后,在其他已认证的应用程序中也会被注销。 3. 服务票据:CAS client可以生成和验证用于应用程序之间安全通信的服务票据。 4. 代理认证:CAS client允许一个已经经过认证的用户代理另一个用户进行认证。 5. 客户端配置:CAS client提供了灵活的配置选项,使开发人员能够根据应用程序的需求进行适当的设置。 总之,CAS client 3.4.1是一个功能强大且稳定的CAS客户端工具包,可以帮助开发人员轻松实现CAS认证和单点登录的功能。它为应用程序提供了一种安全且便捷的用户认证解决方案。 ### 回答2: Cas client 3.4.1是一个客户端的软件,用于与CAS(Central Authentication Service)进行通信和集成。 CAS是一个基于Web的单点登录协议,用于用户身份验证和会话管理。它通过将用户的登录凭证(如用户名和密码)发送到CAS服务器来验证用户身份,并返回一个凭证(票据)以供其他应用程序进行验证。CAS Client 3.4.1是一个针对CAS协议的Java库,用于开发CAS客户端。它提供了一组API和工具,以便应用程序能够有效地与CAS服务器进行通信和集成。 使用CAS Client 3.4.1,开发者可以轻松地将CAS身份验证添加到他们的应用程序中。它提供了一些功能,如自动重定向到CAS登录页面,验证ST(Service Ticket)并获取用户信息等。它还提供了一些配置选项,允许开发者自定义CAS客户端的行为,以适应不同的应用程序需求。 CAS Client 3.4.1具有一些优点。首先,它是一个开源软件,可自由获取和使用。其次,它具有良好的文档和社区支持,开发者可以轻松地获取帮助和解决问题。此外,CAS Client 3.4.1还与许多主流Java框架(如Spring)和应用服务器集成良好,使开发者能够更加方便地集成CAS身份验证到他们的应用程序中。 总结来说,CAS Client 3.4.1是一个方便的Java库,用于与CAS服务器进行通信和集成。它提供了一些功能和配置选项,使开发者能够轻松地将CAS身份验证添加到他们的应用程序中。它是一个受欢迎和广泛使用的CAS客户端解决方案。 ### 回答3: CAS(Central Authentication Service)客户端3.4.1是一个用于集中式身份验证的开源框架。 CAS客户端3.4.1是CAS的一个特定版本,它提供了与CAS服务器进行通信的功能,以进行用户身份验证和单点登录。它可以与各种应用程序和系统集成,包括Web应用程序、移动应用程序和服务。 使用CAS客户端3.4.1,用户可以通过一次登录,获得对多个应用程序的访问权限。当用户尝试访问一个需要身份验证的应用程序时,CAS客户端将重定向用户到CAS服务器进行身份验证。CAS服务器将验证用户的凭证,如用户名和密码,并向应用程序发出一个令牌,表示用户已成功通过身份验证。 CAS客户端3.4.1还支持单点注销功能,当用户注销CAS会话后,所有通过CAS登录的应用程序都会被注销。这可以避免用户需要分别注销每个应用程序的麻烦。 CAS客户端3.4.1是一个功能强大且灵活的身份验证框架,它提供了可靠的身份验证功能,并减少了用户需要记住多个登录凭证的困扰。它被广泛用于大型组织和机构,以确保用户的身份安全和便利的访问多个应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值