从ReentrantLock的lock和unlock 方法跟踪 看AQS源码。
public class Concurrent { public static void main(String[] args) { // 以ReentrantLock 为例进行解读 Lock lock = new ReentrantLock(); lock.lock(); try { }finally { lock.unlock(); } } }
进入ReentrantLock 无参构造类中
无参构造类中, 默认使用的是非公平锁
然后进入NonfairSync 类中 ,继承自Sync 类
Sync类是继承AbstractQueuedSynchronizer类 ,这个类AQS
若是前面没有锁占用,则 将通过CAS 将 state 值 由0设置为1, 表示占用锁。
若是前面有锁占用在执行, 则调用acquire方法
那我们进入acquire方法看下。
acquire 方法里面有 tryAcquire(args), 表示获取锁
查看下nonfairTryAcquire(1);
尝试获取锁,获取不到,才会阻塞自己。
不是当前线程的话, 则进入等待队列中。if(!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
enq 方法则是设置CLH队列, 若是队列中先前没有任务
若是队列中有任务,则进入 if(pred != null){ } 的逻辑
入队操作
进入acquireQueued方法
等待挂起的过程
进入unlock方法
至此算是走完了一个正常的流程
总结, 从ReentrantLock 使用跟踪源码, 可以发现 ReentrantLock 是基于AQS 基石实现的。
AQS 底层主要是通过CLH和 状态state 进行维护的。 AQS中 CLH是虚拟的双向链表结构。
里面有Node 节点 ,这个Node 节点相当于 是一个 队列对象, 对象中包含了 head tail prev next 头尾上下节点, 还有个waitStatus。node里面还有 线程Thread , 相对于 node 节点的 Key ,可以仿照 HashMap 的键值对进行理解。Node 里面还有些枚举状态位。
收录于合集 #同步类AQS
2个
上一篇ReentrantLock和Synchronized简单比较