锁,CAS
Compare-And-Swap 的简称是CAS。 先说CAS吧,CAS 是一种无锁的原子操作,通常用于并发编程中,尤其是多线程环境下对共享资源进行更新时。CAS 操作有三个参数:
内存地址 (V):要修改的变量地址。 预期值 (A):操作之前,期望该变量的值是 A。 新值 (B):如果变量的值是 A,则将其更新为 B。 CAS 操作会检查内存地址中的值是否与预期值相同,如果相同,则将其值更新为新值。如果不同,则不做任何修改,CAS 操作返回失败。
boolean CAS(V memory, A expectedValue, B newValue) {
if (memory == expectedValue) {
memory = newValue;
return true;
} else {
return false;
}
}
CAS 的优势与局限性
优势:
无锁性:CAS 不需要加锁,因此可以有效减少因锁竞争带来的性能开销。
高效性:特别适用于高并发的场景,如计数器、队列等数据结构,避免了线程间的上下文切换和阻塞。
原子性:CAS 操作本身是原子的,可以保证数据的正确性,避免了并发写入导致的数据冲突。
局限性:
ABA 问题:CAS 无法区分“值 A 被更新为 B 后再被更新回 A”的情况,可能会误以为该值没有变化,从而导致错误的操作。为了解决这个问题,通常使用带版本号的 CAS(如 AtomicStampedReference)。
自旋开销:在高并发下,CAS 操作可能会发生大量的重试,导致“自旋”现象,浪费 CPU 资源。
只能修改单一变量:CAS 操作通常只针对一个变量进行修改,无法直接用于更复杂的数据结构(如多个变量的修改),需要组合其他技术。
CAS 在多线程编程中的应用场景有哪些?
计数器:CAS 可用于实现高效的计数器。 无锁队列、栈:CAS 可用于实现高并发环境下的无锁数据结构。 版本控制:结合版本号,CAS 可以实现对对象状态的版本控制。