IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

标签:AQS

共 3 篇相关文章

IT 累计浏览 2,811

【Java并发编程实战】—– AQS(三):阻塞、唤醒:LockSupport

这篇讲的是LockSupport如何作为AQS框架的底层原语,实现线程的阻塞与唤醒。 作者从AQS的获取与释放锁流程切入,指出当线程获取锁失败进入CLH队列后,最终是通过`parkAndCheckInterrupt()`中的`LockSupport.park(this)`挂起的;而在释放锁后,则由`unparkSuccessor()`调用`LockSupport.unpark()`来唤醒队列中的下一个节点。 文章深入解析了LockSupport的核心机制:它基于一个与线程关联的“许可”工作。`park()`会尝试获取许可,若许可不可用则线程休眠;`unpark()`则赋予许可以唤醒目标线程。这种方法比传统的`Thread.suspend()`和`resume()`更安全,因为它不会导致死锁问题。文中也提到,许可不可重入,因此`park()`与`unpark()`通常需要成对使用,并且`unpark()`需要发生在`park()`之后,否则线程不会一直阻塞,还可以通过`parkNanos()`设置超时。 实现上,两者最终都委托给`Unsafe`类的本地方法完成,这展示了Java并发包构建在更底层原语之上的设计思想。

IT 累计浏览 2,880

【Java并发编程实战】—– AQS(二):获取锁、释放锁

这篇讲的是Java并发编程中AQS(抽象队列同步器)如何实现锁的获取与释放,是对AQS底层机制的核心剖析。 作者从锁获取的核心方法 `acquire` 出发,结合源码与流程图,清晰地展示了完整流程:线程首先通过 `tryAcquire` 尝试获取锁;若失败,则通过 `addWaiter` 将自身封装为节点加入CLH队列队尾;随后在 `acquireQueued` 方法中,节点会自旋检查是否为前驱节点且能获取锁,若是则出队,否则通过 `parkAndCheckInterrupt` 挂起等待。文章特别指出了 `tryAcquire` 由具体子类(如ReentrantLock)实现,体现了模板方法模式的设计。 在锁释放部分,流程相对简洁:释放锁时调用 `release` 方法,其核心是 `tryRelease` 修改状态后,通过 `unparkSuccessor` 唤醒队列中下一个有效节点,使等待的线程得以继续尝试获取锁。 通过对 `acquire` 与 `release` 两大核心路径的拆解,这篇文章帮助读者直观理解了AQS如何以CLH队列为骨架,管理锁状态与线程等待,从而掌握ReentrantLock、Semaphore等并发工具背后的统一运行逻辑。

IT 累计浏览 3,210

【Java并发编程实战】—– AQS(一):简介

这篇讲的是Java并发编程中作为JUC同步器基石的AbstractQueuedSynchronizer(AQS)框架的核心原理。作者从ReentrantLock、CountDownLatch等同步器获取锁的不同方法出发,引出对统一框架的需求,从而介绍了AQS的诞生背景。 文章着重解析了AQS实现的三大核心机制。首先,它用一个volatile的int型state变量来表示同步状态,通过CAS操作进行原子更新,这构成了锁获取与释放的状态基础。其次,AQS内部维护了一个变种的CLH双向队列,用于管理等待线程。这个设计的巧妙之处在于,它摒弃了原始CLH的自旋,转而让节点在队列中通过状态位安全地阻塞与唤醒,并能高效处理超时和取消操作。最后,AQS通过队列中Node的SHARED和EXCLUSIVE标记,统一支持了共享锁与互斥锁两种模式。 在阻塞唤醒机制上,AQS没有沿用Java内置锁的wait/notify,而是采用了更底层的LockSupport.park()与unpark()本地方法。整篇文章清晰地勾勒出AQS的骨架,为后续深入分析各类同步器的具体实现打下了扎实的基础。