Java之AQS

AQS是什么

是用来实现锁或者其它同步器组件的公共基础部分的抽象实现,整体就是一个抽象的FIFO队列来完成资源获取线程的安排工作,并通过一个int类变量表示持有锁的状态。
在这里插入图片描述
在这里插入图片描述

使用到AQS的一些类

在这里插入图片描述
ReentranLock:
在这里插入图片描述
CountDownLatch
在这里插入图片描述
ReentrantReadWriteLock:
在这里插入图片描述
Semaphore
在这里插入图片描述

抢到资源的线程直接使用处理业务,抢不到资源的必然涉及一种排队等候机制。抢占资源失败的线程继续去等待(类似银行业务办理窗口都满了,暂时没有受理窗口的顾客只能去候客区排队等候),但等候线程仍然保留获取锁的可能且获取锁流程仍在继续(候客区的顾客也在等着叫号,轮到了再去受理窗口办理业务)
如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到的锁的线程加入到队列中,这个队列就是AQS同步队列的抽象表现。它将要请求共享资源的线程及自身的等待状态封装成队列的结点对象(Node),通过CAS、自旋以及LockSupport.park()的方式,维护state变量的状态,使并发达到同步的效果。

源码说明:

在这里插入图片描述

AQS同步队列的基本结构:

在这里插入图片描述
在这里插入图片描述

AQS内部体系结构

在这里插入图片描述

AQS的内部类Node中的属性说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

从ReentrantLock解读AQS的源码:

在这里插入图片描述

第一步:
在这里插入图片描述

第二步:创建的是公平锁还是非公平锁
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第三:以非公平锁ReentrantLock()为例作为突破走起,方法lock()
对比公平锁和非公平锁的tryAcquire()方法的实现代码,其实差别就在于非公平锁获取锁时公平锁中少了一个判断!hasQueuedPredecessors(),此方法中判断了是否需要排队,导致公平锁和非公平锁的差异如下:
公平锁:公平锁讲究先来先到,线程在获取锁时,如果这个锁的等待队列中已经有线程在等待,那么当前线程就会进入等待队列中;
非公平锁:不管是否有等待队列,如果可以获取锁,则立刻占有锁对象。也就是说队列的第一个排队线程苏醒后,不一定就是排头的这个线程获得锁,它还是需要参加竞争锁(存在线程竞争的情况下),后来的线程可能不讲武德插队夺锁了。
在这里插入图片描述
第四:线程使用lock方法来加锁
以下截图为非公平锁的
在这里插入图片描述
第五:acquire()方法
在这里插入图片描述
第六:tryAcquire方法
在这里插入图片描述
第六,如果线程使用nonfairTryAcquire方法抢占资源失败,则使用addWaiter方法将线程加入等待队列
在这里插入图片描述
在这里插入图片描述
第一次调用enq方法之后会形成以下的样子:
在这里插入图片描述
第七:acquireQueued()方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第八:使用unlock方法来释放锁
在这里插入图片描述
在这里插入图片描述
队列中唤醒的线程再去抢占锁

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值