AQS源码学习

Java并发之AQS详解 - waterystone - 博客园java、多线程、并发、AbstractQueuedSynchronized、AQS、Lock、Mutex、ReentrantLock、Semaphore、CountDownLatch、线程同步https://www.cnblogs.com/waterystone/p/4920797.html学这篇文章中存在几个疑惑的地方做以记录:

1.head节点的线程是当前持有资源可运行的线程,第 二个节点在parkAndCheckInterrupt方法里被park阻 塞,当前一个节点也就是head节点唤醒它后,它才会 成为head节点

2. 其ReentrantLock实现是AQS,它的阻塞底层是使用LockSupport.park方法进行等待的,LockSupport.park是响应中断的,当线程进入ReentrantLock.lock方法里面进行阻塞后,此时调用Thread.interrupt()方法之后,该线程是会被中断被唤醒的,但是唤醒之后,会调用LockSupport.park再次进入等待状态(由于自旋),所以仅从宏观(表面)上面看ReentrantLock.lock是不支持响应中断的,从微观(原理)上面讲ReentrantLock.lock内部确实中断了响应,但是还是会被迫进行等待状态(看acquireQueued这块源码,被唤醒后不符合条件继续进入等等状态,然后通过selfinterrupt方法自我中断,所以Reentrantlock.lock是不响应中断的)。

3.

这个方法中,如果等待的线程没有拿到资源,会一直通过parkAndCheckInterrupt()方法阻塞,只有当前节点是head节点的后继结点时,它才会真正的处于运行状态,否则就算中途被意外中断导致下线程唤醒,通过自旋会继续陷入等待状态。

final boolean acquireQueued(final Node node, int arg) {
 2     boolean failed = true;//标记是否成功拿到资源
 3     try {
 4         boolean interrupted = false;//标记等待过程中是否被中断过
 5         
 6         //又是一个“自旋”!
 7         for (;;) {
 8             final Node p = node.predecessor();//拿到前驱
 9             //如果前驱是head,即该结点已成老二,那么便有资格去尝试获取资源(可能是老大释放完资源唤醒自己的,当然也可能被interrupt了)。
10             if (p == head && tryAcquire(arg)) {
11                 setHead(node);//拿到资源后,将head指向该结点。所以head所指的标杆结点,就是当前获取到资源的那个结点或null。
12                 p.next = null; // setHead中node.prev已置为null,此处再将head.next置为null,就是为了方便GC回收以前的head结点。也就意味着之前拿完资源的结点出队了!
13                 failed = false; // 成功获取资源
14                 return interrupted;//返回等待过程中是否被中断过
15             }
16             
17             //如果自己可以休息了,就通过park()进入waiting状态,直到被unpark()。如果不可中断的情况下被中断了,那么会从park()中醒过来,发现拿不到资源,从而继续进入park()等待。
18             if (shouldParkAfterFailedAcquire(p, node) &&
19                 parkAndCheckInterrupt())
20                 interrupted = true;//如果等待过程中被中断过,哪怕只有那么一次,就将interrupted标记为true
21         }
22     } finally {
23         if (failed) // 如果等待过程中没有成功获取资源(如timeout,或者可中断的情况下被中断了),那么取消结点在队列中的等待。
24             cancelAcquire(node);
25     }
26 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值