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

AbstractQueuedSynchronizer

目录

    • AQS是什么
    • AQS什么样
      • 内部类
      • 成员变量
      • 方法public
      • 如果不使用AQS会怎样
    • AQS的应用
      • ReentrantLock
        • Sync
        • NonfairSync
        • FairSync
      • 其他实现

AQS是什么

AbstractQueuedSynchronizer(AQS)是Java中的一个并发工具,位于java.util.concurrent.locks包中,用于实现基于锁的同步机制。它是许多同步类(如ReentrantLockSemaphore等)的基础,并提供了一种用于实现独占锁(exclusive locks)和共享锁(shared locks)等同步机制的框架。

AQS是一个抽象类,它通过维护一个等待队列来管理线程的同步状态。它的主要设计思想是,当某个线程尝试获取锁时,如果锁不可用,该线程会被放入等待队列,然后被阻塞。当锁释放时,AQS会从等待队列中唤醒适当的线程,使其能够竞争锁。

AQS什么样

内部类

类名作用
NodeNode类表示等待队列中的一个节点,用于构建等待队列、实现线程的阻塞与唤醒,以及表示等待线程。
ExclusiveNodeExclusiveNodeNode类的子类,表示独占模式(exclusive mode)下的节点,用于独占锁的等待队列。
SharedNodeSharedNodeNode类的子类,表示共享模式(shared mode)下的节点,用于共享锁的等待队列。
ConditionNodeConditionNodeNode类的子类,表示条件等待队列中的节点,用于支持条件变量的等待和唤醒机制。
ConditionObjectConditionObjectAbstractQueuedSynchronizer的内部类,用于实现条件变量,允许线程等待特定条件。

这些内部类在AbstractQueuedSynchronizer的实现中扮演着不同的角色,从构建等待队列、表示等待线程、实现条件等待机制,到支持不同模式的锁等待。通过这些内部类的使用,AQS能够支持各种同步场景和锁的实现,从而实现多线程的协调和同步。

成员变量

先看看AQS里都有哪些成员变量:
当然,我可以为您解释这些成员变量的作用。以下是您列出的成员变量的简要解释和作用的表格展示:

变量名变量类型变量作用
WAITINGint表示线程处于等待状态,即等待获取锁。
CANCELLEDint表示线程在等待队列中等待时被取消,即等待被中断或其他原因取消。
CONDNode一个特殊的标识,用于表示等待队列中的节点是一个条件等待节点而不是独占或共享模式的节点。
headNode等待队列中的头节点,即队列中等待时间最长的节点。
tailNode等待队列中的尾节点,即队列中等待时间最短的节点。
stateint表示同步状态的变量,可以是任意整数值,根据具体实现的需要来表示不同的状态。
UUnsafe提供了一些底层的操作,允许直接对内存进行操作,用于实现一些底层同步原语。
STATElong一个偏移量,用于表示在AbstractQueuedSynchronizer类中用于操作state变量的偏移量。
HEADlong一个偏移量,用于表示在AbstractQueuedSynchronizer类中用于操作head变量的偏移量。
TAILlong一个偏移量,用于表示在AbstractQueuedSynchronizer类中用于操作tail变量的偏移量。

这些成员变量在AbstractQueuedSynchronizer中用于维护等待队列、线程状态和同步状态等信息,从而实现了基于队列的线程同步和协调机制。不同的变量在整个机制中扮演着不同的角色,以实现正确的多线程同步行为。

方法public

我们来看一下AQS都提供了哪些方法

方法名参数含义方法作用
acquireint arg:请求获取锁的参数尝试获取锁,如果获取不到则将调用线程置于阻塞状态,直到锁可用或线程被中断。
acquireInterruptiblyint arg:请求获取锁的参数类似于acquire,但是允许线程在等待锁的过程中被中断。如果线程在等待时被中断,会抛出InterruptedException异常。
tryAcquireNanosint arg:请求获取锁的参数,long nanosTimeout:等待时间尝试获取锁,但最多等待指定的时间。如果在超时前未能获取锁,则返回结果指示是否成功获取。
releaseint arg:释放锁的参数释放锁,通常在获取锁成功后调用。释放锁会唤醒等待队列中的其他线程,使其有机会竞争锁。
acquireSharedint arg:请求获取共享锁的参数类似于acquire,但是用于共享锁的获取。多个线程可以同时获取共享锁,而不像独占锁一样只能有一个线程持有。
acquireSharedInterruptiblyint arg:请求获取共享锁的参数类似于acquireShared,但是允许线程在等待共享锁的过程中被中断。如果线程在等待时被中断,会抛出InterruptedException异常。
tryAcquireSharedNanosint arg:请求获取共享锁的参数,long nanosTimeout:等待时间类似于tryAcquireNanos,但是用于共享锁的获取。
releaseSharedint arg:释放共享锁的参数释放共享锁,通常在获取共享锁成功后调用。释放共享锁会唤醒等待队列中的其他线程,使其有机会竞争锁。
hasQueuedThreads-判断是否有线程在等待队列中等待获取锁。
hasContended-判断是否有线程在竞争锁。
getFirstQueuedThread-获取等待队列中的第一个线程,但不移除。
isQueuedThread thread:要检查的线程判断指定线程是否在等待队列中等待获取锁。
apparentlyFirstQueuedIsExclusive-判断等待队列中的第一个线程是否为独占模式(exclusive mode)线程。
hasQueuedPredecessors-判断调用线程是否有在等待队列中的前驱线程。如果有前驱线程,则可能需要执行阻塞操作。
getQueueLength-获取等待队列中的线程数。
getQueuedThreads-获取在等待队列中等待获取锁的所有线程。
getExclusiveQueuedThreads-获取在等待队列中等待获取独占锁的所有线程。
getSharedQueuedThreads-获取在等待队列中等待获取共享锁的所有线程。
toString-返回对象的字符串表示,通常包括等待队列中的线程信息。
ownsThread thread:要检查的线程判断指定线程是否是当前持有锁的线程。
hasWaiters-判断是否有线程在等待队列中等待释放锁。
getWaitQueueLength-获取等待队列中等待释放锁的线程数。
getWaitingThreadsCondition condition:相关的条件获取与指定条件相关的等待线程列表。

这些方法是AbstractQueuedSynchronizer类的核心方法,用于实现多线程同步和协调。

如果不使用AQS会怎样

AQS的应用

我们来直接举个例子

ReentrantLock

ReentrantLock中有3个内部类
在这里插入图片描述

Sync

AQS的子类,其实基本上实现了ReentrentLock的大部分方法,ReentrentLock开放出来的大部分方法其实都是直接调用的Sync里的方法

方法名参数含义方法作用
tryLocklong timeout, TimeUnit unit尝试获取锁,如果锁没有被其他线程持有,则获取锁并返回true,如果在指定的时间内无法获取锁,则返回false。
initialTryLock-作为tryLock的一种形式,是在ReentrantLock的构造函数中使用的,用于初始化锁。
lock-获取锁,如果锁已经被其他线程持有,则当前线程会被阻塞,直到获取到锁。
lockInterruptibly-获取锁,如果锁已经被其他线程持有,允许线程在等待时被中断。如果线程在等待时被中断,会抛出InterruptedException异常。
tryLockNanoslong timeout尝试在指定的时间内获取锁,如果锁没有被其他线程持有,则获取锁并返回true。如果在指定的时间内无法获取锁,则返回false。
tryRelease-尝试释放锁。
isHeldExclusively-判断当前线程是否持有独占锁。
newCondition-创建一个新的Condition对象,用于支持条件等待。
getOwner-获取当前持有独占锁的线程,如果没有线程持有锁,返回null。
getHoldCount-获取当前线程持有锁的次数,用于可重入锁的计数。
isLocked-判断锁是否被任何线程持有。

NonfairSync

Sync的子类,非公平锁的实现。

方法名参数作用
initialTryLockunused尝试获取锁,如果获取成功返回true,失败返回false。该方法只在构造方法中调用一次。
tryAcquireacquires独占式尝试获取同步状态。如果获取成功返回true,否则返回false。

FairSync

Sync的子类,公平锁的实现

方法名参数作用
initialTryLockunused尝试获取锁,当等待队列无线程等待并且state为0。不同于NonfairSync,公平锁只有无竞争时才会尝试获取锁。
tryAcquireacquires尝试获取同步状态,如果队列中第一个节点是当前线程就获取成功,不是则失败。

FairSync也继承自AQS,但实现了公平的锁获取语义 - 等待时间最长的线程最先获得锁。

这两个类开始起作用是在创建ReentrentLock的时候,这里
在这里插入图片描述

其他实现

  • CountDownLatch: 用来进行线程之间同步协作,可以实现一个线程等待其他线程完成某件事情之后再执行。
  • CyclicBarrier: 用来进行线程之间同步协作,可以实现让一组线程达到一个屏障时被阻塞,直到最后一个线程到达屏障时屏障才会开门,所有被屏障拦截的线程才会继续执行。
  • Semaphore: 用于控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。
  • Exchanger: 用于进行线程间的数据交换。它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。
  • BlockingQueue: 一个支持两个附加操作的队列。在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。
  • ForkJoinPool: Fork/Join框架中的线程池实现类,用于异步执行fork/join任务。
http://www.lryc.cn/news/121748.html

相关文章:

  • 谈谈什么是云计算?以及它的应用
  • 【BASH】回顾与知识点梳理(十六)
  • docsify gitee 搭建个人博客
  • SpringBoot2-Tomcat部署
  • Docker查看、创建、进入容器相关的命令
  • leetcode1. 两数之和
  • 温室花卉种植系统springboot框架jsp鲜花养殖智能管理java源代码
  • 测试老鸟经验总结,Jmeter性能测试-重要指标与性能结果分析(超细)
  • IDEA设置Maven自动编译model
  • 关于本地mockjs的使用
  • hive 中最常用日期处理函数
  • 记录一下Java实体转json字段顺序问题
  • 微积分入门:总结归纳汇总(一)
  • ubuntu python虚拟环境venv搭配systemd服务实战(禁用缓存下载--no-cache-dir)
  • 案例15 Spring Boot入门案例
  • 物联网是下一个风口吗?
  • 8月9日上课内容 nginx反向代理与负载均衡
  • 易服客工作室:Elementor AI简介 – 彻底改变您创建网站的方式
  • ClickHouse的数据类型
  • 计算机网络—IP
  • Java 的 Stream
  • SolidUI社区-Discord
  • Spring MVCSpring Boot
  • 01-集群安装JDK(普通用户)
  • 小龟带你妙写排序之选择排序
  • 深入解析 SOCKS5 代理及其在网络安全与爬虫中的应用
  • day9 10-牛客67道剑指offer-JZ66、19、20、75、23、76、8、28、77、78
  • 气体检测仪语音报警芯片,可自行烧录的音频芯片,WT588F02B-8S
  • gdb 调试汇编
  • WebRTC音视频通话-新增或修改SDP中的码率Bitrate限制