Java并发编程-AQS

AQS是Java多线程板块的一个重要概念,很多面试题都会对该内容进行相应的考察。

无论是基于JVM的synchronized还是基于API的ReentrantLock,Semaphore,CountDownlatch底层的实现都少不了抽象队列同步器的概念。


AQS的全名,即AbstractQueuedSynchronizer,其位于java.util.concurrent.locks下,一个重要的线程同步器。

  • 它是构建锁或其他同步组件的基本框架
  • 上面提到的工具全部通过AQ实施
  • 我们还可以使用AQS自定义我们自己的同步组件(例如编写互斥量,twins锁等)
  • AQS的作用是封装如何争夺资源的基本机制,并为程序员提供一种简单的方法来实现资源获取;同时,当获得共享资源失败时,它提供了线程阻塞,排队和唤醒竞争机制来处理这些失败的线程。因此,在使用AQS之后,我们不必担心在定义同步组件时如何实现资源获取。如果我们构建同步队列排队机制,我们可以专注于如何实现自定义组件的逻辑。
  • AQS的核心思想是:如果请求的共享资源是空闲的,则当前请求资源的线程将其设置为有效的工作线程,并且共享资源设置为锁定状态。如果需要占用所请求的共享资源,则需要一组用于线程阻塞和等待和锁定分配的机制。该机制AQS是用CLH队列锁实现的,即无法暂时获取锁的线程将添加到队列中。

AQS实现原理

AQS中维护这一个volatile int state和一个FIFO线程等待队列,当多线程竞争资源时被阻塞会加入该队列。

volatile保证了多线程下的可见性,当state = 1说明当前对象锁已经被占用,其他线程再来加锁时则会失败,加锁失败的线程会被放入一个FIFO等待队列,其会被Unsafe.park()操作挂起,而其他获取所得线程释放锁后,该线程才能被唤醒(允许被中断)。

state的操作是通过CAS来保证其并发修改的安全性。

AQS中关于锁的实现方法:

getState(), 获取锁的标志state

setState(), 设置锁的标志state值

tryAcquaire(int): 独占方式获取锁。 尝试获取资源,成功返回true,否则返回false。

tryRelease(int): 独占方式释放锁。 尝试释放资源,成功返回true,否则返回false。

        具体来说释放独占锁失败的情况会有两种,1. 当前线程并不持有该锁。 2. 释放锁的操作被中断。

对于是否抢占,这关系到阻塞队列是公平的还是非公平的,例如我们使用ReentrantLock就可以自主设置,默认是非公平的。


问:为什么AQS要采用双向链表的数据结构?

首先说双向链表和普通链表的不同,

双向链表有两个指针:

  • 指向前置节点
  • 指向后后继节点

带来的好处是可以支持常量O(1)时间复杂度的情况下找到前驱节点。

更直观的说,双向链表在插入和删除操作的时候,比单向链表更加简单与高效。

具体到AQS的使用背景与链表特性来说有三个原因

1. 没有竞争到锁的线程加入阻塞队列

线程阻塞之前,需要判断前置节点的状态,如果没有prev指针,则需要从head从头找起

2. Lock接口中有一个lockinterruptibly()的方法

void lockInterruptibly() throws InterruptedException;

 处于阻塞的线程允许被中断。

直观来说,一个线程如果竞争资源后被加入阻塞队列,也是允许被中断的,则此时其不需要再存在于阻塞队列当中。

线程状态被标记为cancelled,但是其仍然在双向链表中,我们借助两个指针将其移除,效率很高。避免了锁唤醒操作与遍历的操作产生竞争。

3. 避免了线程阻塞和唤醒的开销

加入到链表中的节点,在尝试竞争锁之前,需要判断自己的前置节点是否为头结点

如果不是头结点,则不需要触发锁的竞争行为。


参考资料:

看完你还敢在简历上写“精通”吗?你说说AQS为什么要用双向链表?【Java面试】_哔哩哔哩_bilibili

说一下AQS的原理? - 记得要让着本宝宝的回答 - 知乎 https://www.zhihu.com/question/483996441/answer/2333128650 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值