图解AQS原理之ReentrantLock详解-非公平锁 (6)

释放锁后,进入到if语句中,判断当前头节点不为空且waitStatus!=0,通过上图也可以发现头节点为-1,则进入到unparkSuccessor方法内:

private void unparkSuccessor(Node node) { /* * 获取节点的waitStatus状态 */ int ws = node.waitStatus; // 如果小于0则设置为0 if (ws < 0) compareAndSetWaitStatus(node, ws, 0); /* * 唤醒下一个节点,唤醒下一个节点之前需要判断节点是否存在或已经被取消了节点,如果没有节点则不需唤醒操作,如果下一个节点被取消了则一直一个没有被取消的节点。 */ Node s = node.next; if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) LockSupport.unpark(s.thread); }

可以看到它是现将头节点的状态更新为0,然后再唤醒下一个节点,如果下一个节点为空则直接返回不唤醒任何节点,如果下一个节点被取消了,那么它会从尾节点往前进行遍历,遍历与头节点最近的没有被取消的节点进行唤醒操作,在唤醒前看一下队列状态:

图解AQS原理之ReentrantLock详解-非公平锁

然后唤醒节点后他会进入到parkAndCheckInterrupt方法里面,再次去执行下面的方法:

final boolean acquireQueued(final Node node, int arg) { boolean failed = true; //取消节点标志位 try { boolean interrupted = false; //中断标志位 for (;;) { final Node p = node.predecessor(); //获取前节点 if (p == head && tryAcquire(arg)) { //这里的逻辑是如果前节点为头结点并且获取到锁则进行头结点变换 setHead(node); p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && //设置waitStatus状态 parkAndCheckInterrupt()) //挂起线程 interrupted = true; } } finally { if (failed) cancelAcquire(node); //取消操作 } }

此时获取p==head成立,并且可以正抢到所资源,所以它会进入到循环体内,进行设置头结点为当前节点,前节点的下一个节点设置为null,返回中断标志,看一下此时队列情况,如下图所示:

图解AQS原理之ReentrantLock详解-非公平锁

AbstractQueuedSynchronizer的独占模式其实提供了三种不同的形式进行获取锁操作,看一下下表所示:

方法名称 方法描述 对应调用的内部方法
acquire   以独占模式进行不间断的获取锁   tryAcquire,acquireQueued  
acquireInterruptibly   以独占模式相应中断的方式获取锁,发生中断抛出异常   tryAcquire,doAcquireInterruptibly  
tryAcquireNanos   以独占模式相应中断的方式并且在指定时间内获取锁,会阻塞一段时间,如果还未获得锁直接返回,发生中断抛出异常   tryAcquire,doAcquireNanos  

通过上面图可以发现,他都会调用图表一中需要用户实现的方法,ReentrantLock实现了独占模式则内部实现的是tryAcquire和tryRelease方法,用来尝试获取锁和尝试释放锁的操作,其实上面内容我们用的是ReentrantLock中的lock方法作为同步器,细心的朋友会发现,这个lock,方法是ReentrantLock实现的,它内部调用了acquire方法,实现了不间断的获取锁机制,ReentrantLock中还有一个lockInterruptibly方法,它内部直接调用的是AbstractQueuedSynchronizer的acquireInterruptibly方法,两个之间的区别在于,两者都会相应中断信息,前者不会做任何处理还会进入等待状态,而后者则抛出异常终止操作,

这里为了详细看清楚它内部关系我这里用张图来进行阐述,如下所示:

图解AQS原理之ReentrantLock详解-非公平锁

左侧代表的事ReentrantLock,右侧代表的AQS

左侧内部黄色区域代表NonfairSync

图中1和2代表AQS调用其他方法的过程

接下来我们来看一下源码信息:

public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyffxz.html