首页 > 其他 > 详细

AQS源码解读:

时间:2021-02-03 18:01:51      阅读:21      评论:0      收藏:0      [点我收藏+]

传入参数为true,是公平锁,false为非公平锁。

技术分享图片

 我们这边解读源码以非公平锁为例来解读:技术分享图片

 compareAndSetState(0, 1)通过CAS设置state状态为1,如果设置成功则加锁成功,设置当前拥有独占访问权限的线程为当前访问线程。后面没有设置成功的线程执行else中的acquire(1)方法。

进入acquire(1)方法中,这个方法中包含了线程入队,尝试拿锁,LockSupport的park()阻塞线程。 

技术分享图片

 首先我们先看下tryAcquire(arg)方法,这个方法会调用nonfairTryAcquire(int acquires),尝试去拿锁。

技术分享图片

 如果tryAcquire(arg)返回为true,取反!tryAcquire(arg)为true,继续往下走,执行acquireQueued(addWaiter(Node.EXCLUSIVE), arg))中的addWaiter(Node.EXCLUSIVE)方法,为当前线程和给定模式创建节点并将其排队。

技术分享图片

  刚开始的时候是第一次进来,所以会走到enq(node)中,如果尾节点为空,则新建一个node节点作为一个傀儡节点,并被头节点指向,然后头,尾节点都指向傀儡节点,但它是处在自旋死循环中,所以又执行一遍,又执行一遍以后,尾节点不为空,执行下面else方法,将当前节点的prev指向原来的tail,当前尾指针执行当前节点,原来的tail节点next指向当前节点。

技术分享图片

 技术分享图片

 如果tail节点不为空,那我们把节点加入到队列里面。如下图逻辑注释所示。

技术分享图片

 然后执行acquireQueued(final Node node, int arg)方法,如下图所示。

技术分享图片

技术分享图片

 当前节点的前一个节点是否等于头节点并且尝试去拿锁,如果满足这两个条件,先把傀儡节点引用指针去掉,使其不被其他节点引用,可以被GC回收掉。然后把当前节点变为傀儡节点。shouldParkAfterFailedAcquire(p, node)方法首次进来的时候,当前节点的前一个节点是傀儡节点,傀儡节点的waitStatus状态为0,会走else的逻辑,通过CAS吧waitStatus值设为-1,然后返回false.

技术分享图片

 

AQS源码解读:

原文:https://www.cnblogs.com/lufei-123/p/14367921.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!