JUC 核心的 AQS的原理

举报
林欣 发表于 2024/09/15 17:49:39 2024/09/15
【摘要】 在Java的并发编程中,java.util.concurrent(简称JUC)包提供了一套丰富的并发工具类,用于帮助开发者简化并发编程的复杂性。其中,AbstractQueuedSynchronizer(简称AQS)是JUC包中的一个核心组件,它提供了一种框架来构建同步器(如锁、信号量等),用于管理那些依赖单个共享资源的多个线程访问。 一、AQS概述AQS是一个用于构建锁和其他同步类的框架,...

在Java的并发编程中,java.util.concurrent(简称JUC)包提供了一套丰富的并发工具类,用于帮助开发者简化并发编程的复杂性。其中,AbstractQueuedSynchronizer(简称AQS)是JUC包中的一个核心组件,它提供了一种框架来构建同步器(如锁、信号量等),用于管理那些依赖单个共享资源的多个线程访问。

一、AQS概述

AQS是一个用于构建锁和其他同步类的框架,它使用了一个int成员变量来表示同步状态,并通过内置的FIFO队列来完成资源获取线程的排队工作。AQS的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要将当前线程加入到等待队列中,并挂起直到被唤醒。

二、AQS的核心组件

  1. 同步状态(State):AQS使用一个volatile修饰的int类型的成员变量来表示同步状态。对于锁来说,这个状态可以表示锁是否被某个线程持有。

  2. 节点(Node):AQS通过内部的CLH(Craig, Landin, and Hagersten)队列的变种来实现线程的排队等待。每个Node代表一个等待获取资源的线程,节点之间通过prev和next指针连接形成双向队列。

  3. 独占模式和共享模式:AQS支持两种同步模式,独占模式和共享模式。独占模式下,一次只有一个线程能持有资源;而在共享模式下,允许多个线程同时持有资源。

三、AQS的工作原理

1. 资源的获取(acquire)

  • 当线程尝试获取资源时,首先会尝试更新同步状态。
  • 如果同步状态允许获取资源(例如,在独占模式下,状态为0表示资源空闲),则获取成功,线程继续执行。
  • 如果同步状态不允许获取资源(例如,状态不为0),则当前线程会被包装成一个Node节点,并加入到等待队列中。
  • 加入队列后,线程会进入一个自旋的过程,不断检查前置节点的状态,直到自己能够被唤醒继续尝试获取资源。

2. 资源的释放(release)

  • 当线程使用完资源后,会释放资源,并尝试唤醒等待队列中的其他线程。
  • 在独占模式下,释放资源通常意味着将同步状态设置为0,并唤醒等待队列中的头节点对应的线程。
  • 在共享模式下,释放资源可能会更新同步状态,但不一定将状态设置为0,同时可能需要唤醒多个等待线程。

四、AQS的优势

  • 简化同步器的实现:AQS提供了一套完整的线程阻塞等待以及唤醒机制,开发者只需要实现状态的检查、状态的更新等核心逻辑,无需关心线程等待队列的维护。
  • 性能高效:AQS通过CAS(Compare-And-Swap)操作来确保同步状态的原子性更新,减少了锁的使用,提高了性能。
  • 灵活性:AQS支持独占和共享两种同步模式,能够满足不同的同步需求。

五、总结

AQS是Java并发框架中的一个重要组件,它提供了一种构建同步器的框架,通过维护一个同步状态和等待队列,实现了线程的阻塞和唤醒,从而简化了同步器的实现。AQS的设计思想体现了Java并发编程中的许多重要概念,如volatile关键字的使用、CAS操作、自旋锁等,是深入理解Java并发编程不可或缺的一部分。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。