原理
<span style="font-size: inherit;">AQS 中维护了一个 FIFO 队列 和 volatile 修饰的status,通过CAS修改status 。</span><br>
要点
1、获取和释放<br>
1、当第一个线程获取锁时,将state替换为1,表示加锁成功,当有其他线程再次获取锁时,尝试获取锁失败,开始尝试加入阻塞队列,addWaiter,进入死循环,再次尝试失败后尝试进入阻塞队列并park当前线程,park前需要保证阻塞队列前一个节点waitStatus 为-1(正常状态为0),用来唤醒后继节点,当前驱节点状态为-1时,加入阻塞队列并park当前线程,队列头节点默认为null称为dummy哑元或哨兵<br>2、释放:队列头节点为-1,唤醒unpark下一个节点,并且把当前头节点移除,下一个节点置为null
2、可重入<br>
判断如果是当前线程获取锁,那么state + 1,表示锁重入
3、可打断<br>
1、不可打断模式,当有其他线程打断时,会继续向下运行,return Thread.interrupted, 清除打断标记,会返回aquireQueue方法,只是做了一个打断标记,继续死循环获取锁,直到获得锁以后,返回上一层,才通过打断标记进行自我打断<br>
2、可打断模式,park时,如果有其他线程打断,直接抛出打断异常
4、公平,非公平
1、非公平锁,先去尝试获取锁,失败后再加入阻塞队列
2、公平锁,先判断阻塞队列有没有前驱节点,有就加入队列
5、Condition<br>每一个条件变量都关联一个等待队列,实现类就是ConditionObject
await<br>
当线程获取锁后,不满足条件后,调用await,进入等待队列中,Node状态为-2
signa<br>
正在执行的线程满足一定条件后,唤醒等待队列中的线程,通过transferForSignal将线程从等待队列中加入阻塞队列中开始去竞争锁
与wait/notify 的区别