aqs速读

原创
2018/10/26 14:07
阅读数 104

说起aqs很多人都感觉很头疼,下文就从几个角度了解,让你快速了解aqs。

预热知识

aqs获取锁等主要用的cas以及locksupport。对锁的控制是一个int类型的状态state。例如获取锁就是通过cas把state从0变成1。

独占锁

图片描述

3个线程都去修改状态,cas只有一个修改成功。剩下的都会失败,并且开始进入一个队列中。 图片描述

线程2,加入队列后,就会判断自己是否可以去抢锁(只有pre是head的才可以抢锁),如果抢不到,就用locksupport挂起。线程3也一样。此时线程2和3都是挂起状态。 图片描述

当1释放锁。释放的过程就是修改状态,例如把1改成0。然后利用locksupport唤醒head的下一个节点。此时2被唤醒再次重复抢锁,失败挂起的流程。

公平锁

经过上面的流程,大家也发现了一个问题,就是修改状态和唤醒节点,不是一个原子操作,如果我刚释放,正好就被一个新的进程修改成功,线程2尝试获取锁是失败的。这就是非公平锁。公平锁,在改状态之前,会先判断一下,等待的队列的头指针和尾指针是否相同(队列是否为空)。这样就保证了队列里的线程有比较高的优先级拿到锁。

重入锁

重入锁就是当前线程已经获取锁了,再次获取锁的时候就可以不用拍在队列里。这个逻辑也是在获取锁的地方判定的,获取锁的时候,判定一下正在拿到锁的线程是否是当前线程。如果是就在状态上+1。释放锁的时候也是+1。直到减到0,才去唤醒阻塞的线程。

共享锁

共享锁其实是多个线程可以同时拿到锁的。流程状态与独占锁没有区别,在阻塞队列里获取锁的时候多了一些操作。释放资源的时候还是唤醒head的下一个节点,那么在共享锁里,就存在一种情况,多个线程同时释放资源唤醒的都是head的next,如果此时只有一个节点获取锁的话,那么资源就浪费了。所以,共享锁在之前的逻辑上多了一步,就是获取锁资源以后,会判断是否还有锁资源。如果有,就再走一次释放锁资源的过程。让后续的节点继续获取资源。

小结

对于aqs。主流程就是,尝试获取锁资源,失败入队列,再次获取锁,失败后,等待被唤醒,唤醒后继续获取锁资源,然后根据锁的类型再处理情况。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部