说起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。主流程就是,尝试获取锁资源,失败入队列,再次获取锁,失败后,等待被唤醒,唤醒后继续获取锁资源,然后根据锁的类型再处理情况。
共同学习,写下你的评论
评论加载中...
作者其他优质文章