AQS源码
参考:
- https://blog.csdn.net/TZ845195485/article/details/109210095
- https://www.cnblogs.com/xuyin2010/p/14764942.html
AQS的CLH队列
AQS有一个volatile修饰的int类型状态码,分为三种状态:0没有任务,1被占用,大于1可重入锁。
有一个Node节点构成的双向链表,用于储存等待共享资源的线程。
还有一个Conditional链表,用于
ReentrantLock加锁的过程:
- 首先调用lock方法,如果是非公平锁则会先CAS尝试获取锁,成功的话就插队执行。失败了就acquire(1),入队等待。公平锁就直接入队等待。
- acquire(1)-》先tryAcquire(1)【尝试获取锁】,失败的话就调用addWaiter入队,采用尾插法。【每添加一个节点,就会将CANCELLED=1的节点删除】
- 之后就是队伍内的处理。如果前一个节点不是头节点,就会把前一个节点的状态(waitStatus)置为-1,如果前一个节点已经是-1状态了,就会调用LockSupport阻塞当前节点的线程。
- 直到占有AQSstatus的线程结束,唤醒了第二个节点,然后第二个节点的线程获取到锁状态 。将第二个节点置为头节点(thread=null, waitStatus=0),原本的头节点会被GC。
lockInterruptibly()
在节点入队列的过程和获取锁的过程是不响应中断的,其他时候都会做中断判断,有的话抛出中断异常。
条件队列
- 条件队列建立在某个具体的锁上,只有先获取锁才能使用条件队列
- 条件队列的唤醒,就是把节点从条件队列移到同步队列,使得节点有机会获取锁。