比较并交换(compare and swap, CAS)

参考:维基百科

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

int cas(long *addr, long old, long new)
{
    /* Executes atomically. */
    if(*addr != old)
        return 0;
    *addr = new;
    return 1;
}

在使用上,通常会记录下某块内存中的旧值,通过对旧值进行一系列的操作后得到新值,然后通过CAS操作将新值与旧值进行交换。如果这块内存的值在这期间内没被修改过,则旧值会与内存中的数据相同,这时CAS操作将会成功执行 使内存中的数据变为新值。如果内存中的值在这期间内被修改过,则一般来说旧值会与内存中的数据不同,这时CAS操作将会失败,新值将不会被写入内存。
在应用中CAS可以用于实现无锁数据结构,常见的有无锁队列(先入先出)以及无锁栈(先入后出)。对于可在任意位置插入数据的链表以及双向链表,实现无锁操作的难度较大。
在这里插入图片描述
使用CAS操作的做法趋于乐观锁,总是假设被操作值未曾被改变(即与旧值相等),并一旦确认这个假设的真实性就立即进行值替换。在被操作值被频繁变更的情况下,CAS操作并不那么容易成功所以需要不断进行尝试,直到成功为止。
而使用互斥锁的做法则趋于悲观,我们总假设会有并发的操作要修改被操作的值,并使用锁将相关操作放入临界区中加以保护。
例:点赞问题。两个线程同时要让点赞数量+1,现在同时去读点赞数是10,然后线程一写11,线程二写11,出现读写冲突。现在使用CAS把整个操作打包给CPU和操作系统。两个线程都读到点赞数是10,都想给点赞数+1,然后两个线程都调用CAS,CAS是原子操作,线程1先判断点赞数是不是10,如果是10则锁住然后改为11。线程2判断点赞数不是10,重试。
两个原子操作绝不可能并发的访问同一个变量。

读取或写入一个原子对象是一个原子操作,也就是说它是不能被中断的操作。这意味着:不同的线程可以同时访问一个原子对象而不引起竞态条件。对于每个原子对象,对象的所有修改以一个确定的全局化次序执行,这称为该对象的修改次序(modification order)。
处理器保证从系统内存当中读取或者写入一个字节是原子的,意思是当一个处理器读取一个字节时,其他处理器不能访问这个字节的内存地址。

<think>嗯,用户想了解CASCompare-And-Swap操作及其实现。首先,我需要回忆一下CAS的基本概念。CAS是一种原子操作,用于在多线程环境中实现同步,而无须使用锁。它比较内存中的值与预期值,如果相同,则更新为新值。否则,不做任何操作。这个机制在无锁数据结构和算法中非常有用,比如发队列或计数器。 接下来,用户提到了具体的实现问题,可能需要了解不同编程语言中的CAS支持。例如,在C/C++中,有原子库中的函数,比如std::atomic_compare_exchange_strong。在Java中,有java.util.concurrent.atomic包中的类,如AtomicInteger的compareAndSet方法。此外,用户提供的引用中提到了关于结构体比较的问题,需要注意编译器是否允许比较复杂类型,可能需要特殊处理。 然后,我需要考虑CAS的应用场景和潜在问题。应用场景包括无锁数据结构、计数器、状态机等。问题方面,ABA问题是一个经典问题,即在CAS操作期间,变量被其他线程修改后又改回原值,导致CAS错误地认为没有变化。解决方案通常包括使用版本号或标记指针。另外,CAS在高竞争情况下可能导致性能问题,因为不断重试会增加CPU开销,如引用[1]中提到的CPU缓存未命中问题。 用户提供的引用中,引用[1]解释了CAS的基本逻辑和假设,引用[2]指出结构体比较的限制,引用[4]提到了WRRM模式,这可能与CAS的使用场景有关。需要将这些内容整合到回答中,确保引用正确。 在实现部分,用户可能需要示例代码。例如,展示如何在C++中使用原子操作实现CAS,或者用伪代码说明算法流程。同时,需要指出不同语言的不同实现方式,以及如何处理结构体或复杂类型的比较,如引用[2]中提到的问题。 另外,需要强调CAS的开销和适用场景,比如低竞争环境下的高效性,高竞争下的性能下降。可能还需要提到优化方法,如退避策略、批量操作等,引用[1]中的commit-retry模式可能与此相关。 最后,生成的相关问题需要涵盖CAS的原理、实现细节、问题与优化、应用场景等,确保覆盖用户可能感兴趣的各个方面。</think>### CASCompare-And-Swap操作及实现 #### 1. **CAS基本概念** CASCompare-And-Swap)是一种原子操作,用于实现多线程环境下的无锁同步。其核心逻辑为: - 比较内存位置的值与预期值; - 若相等,则将该位置更新为新值; - 若不等,则放弃操作(可能需要重试)。 其伪代码可表示为: ```c bool CAS(int* ptr, int expected, int new_value) { if (*ptr == expected) { *ptr = new_value; return true; } return false; } ``` 在实际硬件中,该操作通过单条指令(如x86的`CMPXCHG`)实现原子性[^1]。 #### 2. **CAS的典型应用** - **无锁数据结构**:如发队列、栈、计数器等; - **状态机更新**:确保状态变更的原子性; - **资源管理**:例如引用计数(避免重复释放)。 例如,线程安全的计数器实现: ```c++ #include <atomic> std::atomic<int> counter(0); void increment() { int old_val = counter.load(); while (!counter.compare_exchange_weak(old_val, old_val + 1)) {} } ``` 此处`compare_exchange_weak`为CAS的封装,若失败则自动重试。 #### 3. **CAS的实现细节** - **硬件支持**:依赖CPU指令(如x86的`CMPXCHG`,ARM的`LDREX/STREX`); - **编译器封装**:C++的`std::atomic`、Java的`AtomicInteger`等; - **ABA问题**:若值从A→B→A,CAS可能误判未修改。解决方案包括: - 使用带版本号的指针(如`std::atomic<uintptr_t>`结合标记位); - 引入中间状态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值