当前位置: 首页 > news >正文

CAS、CAS自旋、CAS自旋锁、CLH锁与Java AQS:深入理解并发编程核心机制


CAS、CAS自旋、CAS自旋锁、CLH锁与Java AQS:深入理解并发编程核心机制


1. CAS(Compare and Swap)

什么是CAS?

CAS(Compare and Swap)是一种无锁(Lock-Free)的原子操作,用于在多线程环境下实现数据同步。其核心思想是:

  • 比较内存中的值与预期值是否一致,若一致则更新为新值,否则不修改。
  • 整个过程是原子的,由底层硬件(如CPU的CMPXCHG指令)直接支持。
CAS在Java中的实现

Java通过Unsafe类和原子类(如AtomicInteger)提供CAS支持:

public class AtomicInteger {public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}
}

示例

AtomicInteger count = new AtomicInteger(0);
count.compareAndSet(0, 1); // 成功将0改为1
CAS的优缺点
  • 优点
    • 避免锁竞争,减少线程切换开销。
    • 适用于低冲突场景(如计数器、标志位更新)。
  • 缺点
    • ABA问题:值从A→B→A,CAS无法感知中间变化。
      解决方案:使用版本号(如AtomicStampedReference)。
    • 自旋开销:长时间失败可能导致CPU空转。

2. CAS自旋与CAS自旋锁

CAS自旋(Spin)

CAS自旋是指线程在CAS失败后循环重试,直到成功。
示例:实现一个简单的自增操作:

public class SpinCounter {private AtomicInteger value = new AtomicInteger(0);public void increment() {int oldVal;do {oldVal = value.get();} while (!value.compareAndSet(oldVal, oldVal + 1));}
}
CAS自旋锁(Spin Lock)

基于CAS自旋实现的锁,线程在获取锁失败时不会阻塞,而是循环尝试。
示例

public class SpinLock {private AtomicBoolean locked = new AtomicBoolean(false);public void lock() {while (!locked.compareAndSet(false, true)) {// 自旋等待}}public void unlock() {locked.set(false);}
}

缺点

  • 高竞争下CPU利用率高,适用于临界区极短的场景(如操作系统内核)。

3. CLH锁

CLH锁的设计思想

CLH(Craig, Landin, Hagersten)锁是一种基于链表的队列锁,通过隐式队列管理线程,减少缓存一致性流量。

  • 核心结构:每个线程持有一个节点(Node),包含一个volatile布尔字段locked
  • 加锁流程
    1. 线程创建一个节点,locked设为true
    2. 将前驱节点的locked字段作为自旋条件。
    3. 当前驱节点释放锁(locked=false),当前线程获取锁。
CLH锁的Java伪代码
public class CLHLock {private static class Node {volatile boolean locked = true;}private final ThreadLocal<Node> myNode = ThreadLocal.withInitial(Node::new);private final AtomicReference<Node> tail = new AtomicReference<>();public void lock() {Node node = myNode.get();Node pred = tail.getAndSet(node);while (pred != null && pred.locked) {// 自旋等待前驱节点释放锁}}public void unlock() {myNode.get().locked = false;myNode.remove(); // 清理线程本地状态}
}
CLH锁的优势
  • 公平性:严格按请求顺序获取锁。
  • 低缓存一致性开销:线程仅监视前驱节点的状态,减少总线风暴。

4. Java AQS(AbstractQueuedSynchronizer)

AQS的核心设计

AQS是Java并发包(java.util.concurrent)的核心框架,用于构建锁和同步器(如ReentrantLockSemaphore)。

  • 核心思想
    • 通过一个volatile int state表示同步状态(如锁的重入次数、信号量许可数)。
    • 使用CLH变体的双向队列(FIFO)管理等待线程。
AQS的模板方法模式

AQS提供需子类实现的抽象方法(如tryAcquiretryRelease),开发者只需关注状态管理逻辑。
示例:实现一个独占锁:

public class SimpleLock extends AbstractQueuedSynchronizer {@Overrideprotected boolean tryAcquire(int arg) {return compareAndSetState(0, 1); // 通过CAS获取锁}@Overrideprotected boolean tryRelease(int arg) {setState(0); // 释放锁return true;}public void lock() {acquire(1);}public void unlock() {release(1);}
}
AQS的同步队列
  • 队列节点(Node)
    每个节点保存线程引用、等待状态(如CANCELLEDSIGNAL)和前驱/后继指针。
  • 入队与出队
    • 线程获取锁失败时,被包装为Node加入队列尾部。
    • 前驱节点释放锁后,唤醒后继节点。
AQS与CLH锁的关系

AQS的同步队列是CLH锁的变体:

  • 将CLH的隐式队列改为显式的双向链表。
  • 支持中断、超时和条件变量(Condition)。

5. 对比总结

机制特点适用场景
CAS无锁原子操作,依赖硬件指令简单状态更新(如计数器)
CAS自旋锁基于CAS的自旋,无队列管理临界区极短,低竞争环境
CLH锁公平锁,基于隐式队列,减少缓存一致性流量高并发公平锁需求
AQS提供同步框架,支持独占/共享模式、条件变量构建复杂同步器(如ReentrantLock)

6. 实际应用

  • ReentrantLock:基于AQS实现可重入锁,支持公平/非公平模式。
  • Semaphore:通过AQS管理许可数量。
  • CountDownLatch:利用AQS的共享模式实现线程协作。

7. 性能优化与注意事项

  • 减少CAS竞争:通过分段锁(如ConcurrentHashMap)或缓存行填充(避免伪共享)。
  • 避免长时间自旋:结合自旋与阻塞(如AQS的自旋后挂起)。
  • 条件变量的正确使用:始终在循环中检查条件(防止虚假唤醒)。

8. 总结

CAS、自旋锁、CLH锁和AQS构成了Java并发编程的底层基石:

  • CAS提供了无锁编程的基础。
  • 自旋锁优化了短临界区的性能。
  • CLH锁通过队列化降低了竞争开销。
  • AQS整合了这些机制,为高级同步器提供了灵活的实现框架。

理解这些机制的原理与实现,是编写高效、健壮并发代码的关键。

相关文章:

  • stable diffusion的attention-map:提取和可视化跨注意力图
  • DRAM详解
  • 【Electron】electron-vue 借助 element-ui UI 库助力桌面应用开发
  • MIST:一键解锁 macOS 历史版本,旧系统安装不再难!
  • 学习黑客 MAC 地址深入了解
  • 问题 | 低空经济未来发展前景机遇及挑战
  • C++ 工具链与开发实践:构建安全、高效与创新的开发生态
  • 探索大语言模型(LLM):词袋法(Bag of Words)原理与实现
  • 【愚公系列】《Manus极简入门》026-市场分析专家:“市场洞察家”
  • 【JavaScript】二十九、垃圾回收 + 闭包 + 变量提升
  • Python实例题:Python获取喜马拉雅音频
  • laravel 使用异步队列,context带的上下文造成反序列化出问题
  • day05_java中常见的运算符
  • python学生作业提交管理系统-在线作业提交系统
  • Hutool的`BeanUtil.toBean`方法详解
  • 自定义Widget开发:自定义布局实现
  • Spring Boot Controller 如何处理HTTP请求体
  • 力扣刷题Day 42:缺失的第一个正数(238)
  • javaStream流toMap小坑
  • 算法与数据结构 - 常用图算法总结
  • 105岁八路军老战士、抗美援朝老战士谭克煜逝世
  • 8大类1000多支,中国红十字会已建成10万人规模救援队伍
  • 甘怀真:天下是神域,不是全世界
  • 指挥家高健:东方市民音乐会“高贵不贵”,我愿意常来
  • 五一假期上海边检查验出入境人员超61万人次,同比增长23%
  • 五一假期,长三角铁路张家港、台州等多个车站客发量创新高