CAS - 原理简介

        CAS是JDK提供的非阻塞原子操作,它通过硬件保证了比较-更新的原子性。它是非阻塞的且自身具有原子性,也就是说CAS效率高、可靠。CAS是一条CPU的原子指令(cmpxchg指令),不会造成所谓的数据不一致问题,Unsafe类提供的CAS方法(如:compareAndSwapXXX)底层实现就是CPU的cmpxchg指令。

        执行cmpxchg指令指令的时候,会判断当前系统是否为多核系统,如果是就给总线加锁,只有一个线程会对总线加锁成功,加锁成功之后会执行cas操作,也就是说CAS的原子性实际上是CPU实现独占的,比起用synchronized重量级锁,这里的排他时间很短,所以多线程情况下性能会比较好。

        CAS,compare and swap的缩写,中文翻译成比较并交换,实现并发算法时常用的一种技术。它包含三个操作数:内存位置、预期原值、更新值。执行CAS操作的时候,将内存位置的值与预期原值进行比较:

  1. 如果匹配,那么处理器会自动将该位置的更新为新值。
  2. 如果不匹配,处理器不做任何操作或者重试,当它重试这种行为我们称之为:自旋。多个线程同时执行CAS操作只会有一个线程成功。

 

没有CAS之前

        有个Resource资源类,为了保证addNumber()方法中的number++的原子性,我们必须使用synchronized将该方法上锁。

class Resource {
​​​​​​​
    //保证可见性
    volatile Integer number = 0;

    public Integer getNumber() {
        return number;
    }

    //加锁保证原子性
    public synchronized void addNumber() {
        number++;
    }
}

使用CAS

        如果使用AtomicInteger原子整型类,我们就不需要synchronized这样重量级的锁来保证多线程环境下的并发问题导致的问题。

class Resource {

    private AtomicInteger atomicInteger = new AtomicInteger();

    public Integer getAtomicInteger() {
        return atomicInteger.get();
    }

    public void setAtomicInteger() {
        atomicInteger.getAndIncrement();
    }
}

        使用100个线程,每个线程对atomicInteger 进行加100次。逻辑上我们的最终打印的结果应该是:10000。

    //线程数
    private static final Integer THREAD_COUNTS = 100;
    private static final CountDownLatch countDownLatch = new CountDownLatch(THREAD_COUNTS);

    public static void main(String[] args) {

        Resource resource = new Resource();

        for (int i = 0; i < THREAD_COUNTS; i++) {
            new Thread(() -> {
                //每个线程加100次
                for (int j = 0; j < 100; j++) {
                    resource.setAtomicInteger();
                }
                countDownLatch.countDown();
            }, "线程:" + i).start();
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("得到最终值:" + resource.getAtomicInteger());
    }

        打印结果:

得到最终值:10000
cas-client-autoconfig-support是一个CAS客户端自动配置模块,它可以帮助开发人员快速地将Java Web应用程序集成到CAS单点登录系统中。 使用教程: 1. 下载cas-client-autoconfig-support的jar包并加入项目依赖中。 2. 在web.xml文件中添加如下配置: ``` <filter> <filter-name>CAS Single Sign Out Filter</filter-name> <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS Single Sign Out Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>CAS Authentication Filter</filter-name> <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class> <init-param> <param-name>casServerLoginUrl</param-name> <param-value>https://cas.example.com/login</param-value> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://example.com</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Authentication Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class> </listener> <listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class> </listener> ``` 其中,casServerLoginUrl参数是CAS服务器的登录地址,serverName参数是本应用程序的地址。 3. 在Spring配置文件中添加如下配置: ``` <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator"> <constructor-arg index="0" value="https://cas.example.com" /> </bean> <bean id="casAuthenticationEntryPoint" class="org.jasig.cas.client.authentication.CasAuthenticationEntryPoint"> <property name="loginUrl" value="https://cas.example.com/login" /> <property name="serviceProperties" ref="serviceProperties" /> </bean> <bean id="serviceProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="properties"> <props> <prop key="service">http://example.com</prop> </props> </property> </bean> <bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter"> <property name="authenticationManager" ref="authenticationManager" /> <property name="authenticationSuccessHandler" ref="successHandler" /> </bean> <bean id="successHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"> <property name="defaultTargetUrl" value="/index.jsp" /> </bean> <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager"> <property name="providers"> <list> <ref local="casAuthenticationProvider" /> </list> </property> </bean> <bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"> <property name="ticketValidator" ref="ticketValidator" /> <property name="authenticationUserDetailsService" ref="authenticationUserDetailsService" /> <property name="serviceProperties" ref="serviceProperties" /> <property name="key" value="casAuthProviderKey" /> </bean> <bean id="ticketValidator" class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator"> <constructor-arg index="0" value="https://cas.example.com" /> </bean> <bean id="authenticationUserDetailsService" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"> <constructor-arg ref="userDetailsService" /> </bean> <bean id="userDetailsService" class="com.example.MyUserDetailsService" /> ``` 其中,casServerLoginUrl参数和serviceProperties的配置与web.xml中的相同,authenticationManager是Spring Security的认证管理器,authenticationUserDetailsService和userDetailsService是用户信息服务。 原理解析: cas-client-autoconfig-support的原理是使用Java的反射机制,动态地加载CAS客户端的配置信息并注入到Java Web应用程序中。在web.xml文件中,CAS客户端的filter和listener是必须的,它们可以监听用户的会话状态并在用户退出登录时向CAS服务器发送注销请求。在Spring配置文件中,CAS客户端的认证过程是通过Spring Security框架实现的,它将CAS服务器返回的票据进行验证,并将用户信息封装成Spring Security认证对象。用户信息可以从数据库、LDAP等数据源中获取。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值