资讯专栏INFORMATION COLUMN

CAS

joy968 / 2612人阅读

摘要:与同步方式在多线程情况下,可以采用同步阻塞悲观锁或乐观锁的方式实现业务,具体要看业务场景,如果重试的代价很小,那用是合适的,但如果每次重试都需要花费大量的时间或资源,那应该采用同步方式。

CAS介绍

CAS - Compare And Swap (Compare And Set, Check And Set)

wikipedia的描述如下:

比较并交换(compare and swap, CAS),是原子操作的一种,可用于在多线程编程中实现不被打断的数据交换操作,从而避免多线程同时改写某一数据时由于执行顺序不确定性以及中断的不可预知性产生的数据不一致问题。 该操作通过将内存中的值与指定数据进行比较,当数值一样时将内存中的数据替换为新的值。

Java在sun.misc.Unsafe类库里面的CAS实现。

以下源码摘自java.util.concurrent.locks.AbstractQueuedSynchronizer

/**
 * Atomically sets synchronization state to the given updated
 * value if the current state value equals the expected value.
 * This operation has memory semantics of a {@code volatile} read
 * and write.
 *
 * @param expect the expected value
 * @param update the new value
 * @return {@code true} if successful. False return indicates that the actual
 *         value was not equal to the expected value.
 */
protected final boolean compareAndSetState(int expect, int update) {
    // See below for intrinsics setup to support this
    //this: 当前对象
    //stateOffSet: 偏移量,声明在下面已贴出
    //expect: 期待值
    //update: 更新值
    //如果stateOffSet的值与expect相等,则将stateOffset的值更新为update;并返回true。
    //否则不更新,并返回false。
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
    
    ......
    
private static final long stateOffset;

static {
    try {
        stateOffset = unsafe.objectFieldOffset
            (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
        
            ......

    } catch (Exception ex) { throw new Error(ex); }
}
    
CAS与同步方式

在多线程情况下,可以采用同步阻塞(悲观锁)或CAS(乐观锁)的方式实现业务,具体要看业务场景,如果重试的代价很小,那用CAS是合适的,但如果每次重试都需要花费大量的时间或资源,那应该采用同步方式。

以下是2种方式的简单举例:

class MyLock {

    private boolean locked = false;

    public synchronized boolean lock() {
        if(!locked) {
            locked = true;
            return true;
        }
        return false;
    }
}
public static class MyLock {
    private AtomicBoolean locked = new AtomicBoolean(false);

    public boolean lock() {
        return locked.compareAndSet(false, true);
    }

}
CAS缺点 - ABA问题
进程P1读取了一个数值A
P1被挂起(时间片耗尽、中断等),进程P2开始执行
P2修改数值A为数值B,然后又修改回A
P1被唤醒,比较后发现数值A没有变化,程序继续执行。

解决思路:在每次更新的同时附上版本号,如:1A -> 2B -> 3A。JDK1.5开始新增的java.util.concurrent.atomic.AtomicStampedReference就是一种实现方式。

Redis中的CAS

Redis可以使用WATCH来实现对事务中键(可以是多个键)的监视,如果至少有一个键在EXEC执行前被改动,那么整个事务都会被取消, EXEC返回nil-reply来表示事务已经失败。

具体参见:Redis - 事务(transactions)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69256.html

相关文章

  • CAS 5.2.x 单点登录 - 搭建服务端和客户端

    摘要:一简介单点登录,简称为,是目前比较流行的企业业务整合的解决方案之一。客户端拦截未认证的用户请求,并重定向至服务端,由服务端对用户身份进行统一认证。三搭建客户端在官方文档中提供了客户端样例,即。 一、简介 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系...

    Lin_YT 评论0 收藏0
  • 统一认证 - Apereo CAS 客户端的集成以及小结

    摘要:所以客户端的集成主要是单点登录的集成,客户端指定需要做安全认证的页面,然后的安全包检测校验用户登录情况,并自动与登录页面进行跳转交互。提供了很多配置的方式,有,,以及其他可查官网。但高度自由的一如既往的,没有提供可视化操作的界面。 前两篇介绍了Apereo CAS以及服务器端的安装,但还不够完整,服务端还没有Application真正用起来呢!这篇文章将介绍怎么用起来 集成的目的 客户...

    AbnerMing 评论0 收藏0
  • spring系列---CAS客户端与SpringSecurity集成

    摘要:客户端与集成指定端口请求路径用于单点退出,该过滤器用于实现单点登出功能,可选配置该过滤器用于实现单点登出功能,可选配置。该过滤器使得开发者可以通过来获取用户的登录名。 CAS客户端与SpringSecurity集成 pom.xml org.springframework spring-context 4.3.9....

    hizengzeng 评论0 收藏0
  • 从http验证流程解析CAS单点登录

    JAVA单点登录有好多种方式,譬如用cookie的domain做,用中间代理做等等,但都需要自行做许多开发工作。而其中耶鲁大学的开源项目CAS提供了一个一站式解决方案,只需很少的扩展即可轻松实现企业级单点登录。基础知识网上其他挺多的,这里我就不详述了。本文通过分析http请求过程中httpheader,cookie等数据剖析了cas(非代理模式,默认验证逻辑。其他如restletAPI等可扩展逻辑...

    honhon 评论0 收藏0
  • 前后端分离下的CAS跨域流程分析

    摘要:这种情况通常发生在反向代理的时候,前端发起请求代理服务器,代理服务器发起请求到,这时候就容易导致域名不一致,请一定要注意这点。 写在最前 前后端分离其实有两类: 开发阶段使用dev-server,生产阶段是打包成静态文件整个放入后端项目中。 开发阶段使用dev-server,生产阶段是打包成静态文件放入单独的静态资源服务器中,如nginx。 这两种方案最大的区别就是生产阶段。由于第...

    ckllj 评论0 收藏0
  • 前后端分离下的CAS跨域流程分析

    摘要:这种情况通常发生在反向代理的时候,前端发起请求代理服务器,代理服务器发起请求到,这时候就容易导致域名不一致,请一定要注意这点。 写在最前 前后端分离其实有两类: 开发阶段使用dev-server,生产阶段是打包成静态文件整个放入后端项目中。 开发阶段使用dev-server,生产阶段是打包成静态文件放入单独的静态资源服务器中,如nginx。 这两种方案最大的区别就是生产阶段。由于第...

    DevTalking 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<