简单聊下AQS

1.是什么

aqs即AbstractQueueSynchronizer。是并发大神doug lea的杰作。是java中一系列锁实现的基础,

比如常用的可重入锁ReentrantLock,CountDownLatch,Semaphore。

2.实现

状态state+CLH队列

根据当前state是否为0判断是否可以获取锁,队列是一个双向队列,其中每个结点有排队线程,结点的信号等信息。

以非公平锁为了,我们在外界调用lock方法的时候,源码是这样实现的

1):CAS尝试获取锁,获取成功则可以执行同步代码

2):CAS获取失败,则调用acquire方法,acquire方法实际上就是AQS的模板方法

3):acquire首先会调用子类的tryAcquire方法(又回到了ReentrantLock中)

4):tryAcquire方法实际上会判断当前的state是否等于0,等于0说明没有线程持有锁,则又尝试CAS直接获取锁

5):如果CAS获取成功,则可以执行同步代码

6):如果CAS获取失败,那判断当前线程是否就持有锁,如果是持有的锁,那更新state的值,获取得到锁(这里其实就是处理可重入的逻辑)

7):CAS失败&&非重入的情况,则回到acquire方法执行acquireQueued(addWaiter(Node.EXCUSIVE))「入队列」的操作,这里如果head和tail都为空,会先初始化一个空的node,作为哨兵结点,所以队列头节点始终是一个空值的node(信号量有值)

哨兵结点的作用?不用频繁判空,保持代码一致性。

8):将节点入队列之后,会判断「前驱节点」是不是头节点,如果是头结点又会用CAS尝试获取锁

9):如果是「前驱节点」是头节点并获取得到锁,则把当前节点设置为头结点,并且将前驱节点置空(实际上就是原有的头节点已经释放锁了)

10):没获取得到锁,则判断前驱节点的状态是否为SIGNAL,如果不是,则找到合法的前驱节点,并使用CAS将状态设置为SIGNAL

11):最后调用LockSupport.park(属于native本地方法)将当前线程挂起

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值