(一)AQS全名:AbstractQueueSynchronizer,提供了FIFO队列,内部有的主要字段:
private volatile int state; 全局的一个状态字段,不同的实现可以不同的用法。 比如countDownLatch的时候,state初始是一个传入的总值,每当执行一个countDown方法时,state减一直到为0时,就unpark等待的线程。 比如ReentrantLock的时候,state初始为0,大于0时,就说明有线程已经获取到锁。重入锁时,state可以持续增加。释放锁时,就会unpark队列的第一个节点进行唤醒。 private transient volatile Node head; 队列头节点,头节点不存信息,next的下一个节点存信息。 private transient volatile Node tail; 队列尾节点 其中Node结构 static final class Node { int waitStatus; 状态标记,主要是记录这个队列中的这个节点后续还需要执行不 Node prev; 前一个节点 Node next; 下一个节点 Node nextWaiter; 在等待队列中的下一个节点 Thread thread; 入队列的线程 } waitStatus:表示节点的状态,其中包含的状态有: CANCELLED:值为1,表示当前节点被取消; SIGNAL:值为-1,表示当前节点的的后继节点将要或者已经被阻塞,在当前节点释放的时候需要unpark后继节点; CONDITION:值为-2,表示当前节点在condition等待队列中; PROPAGATE:值为-3,表示releaseShared需要被传播给后续节点(仅在共享模式下使用); 0:无状态,表示当前节点在队列中等待获取锁。 AQS内部提供了上面的这个队列和一些cas指令来改变state状态的操作,
(二)CountDownLatch原理:
在new CountDownLatch(5)时,AQS中的state就为5,主线程执行await时,会判断sate值是否为0,不为0就调用LockSupport.park进行阻塞主线程,当其他地方执行了countDown方法,就会将state进行减1,如果减到了0,则调用LockSupport.unpark唤醒在AQS队列中的这一条主线程等待节点。
(三)ReentrantLock原理:通过CAS指令 + AQS队列实现对线程加锁。
结构:ReentrantLock实现接口Lock的lock()和unLock()方法,内部有两个内部类公平锁FairSync和非公平锁NonfairSync,这两个类均继承了AbstractQueueSynchronizer(里面存有Node双向链表组成一个队列,还有head,tail节点,state状态,waitStatus状态)
一、非公平锁加锁过程:
1、当线程调用lock方法获取锁,通过cas的方式去设置state状态获取锁,如果获取成功则将exclusiveOwnerThread变量设置为当前线程。并返回true。业务正常执行。
2、当第一次获取锁失败后,判断state是否为0,如果不为0,则判断当前线程是否与exclusiveOwnerThread线程一样(可重入性),相当则state加1,返回true。 如果state==0,则继续尝试获取锁,若获取成功,则设置变量并返回true。
若返回为false,则进入如下面第三步。
3、创建一个node节点并进行入队列:pre指向tail节点,tail节点的next执行新节点。
4、队列中节点的waitStatus状态进行设置:如果新节点的pre节点waitStatus状态是singnal(-1),则通过LockSupprt.park方法阻塞当前线程。(内部是调用unsafe的方法对线程),如果新节点的pre节点是大于0,说明这些节点已经废弃,可以跳过,直接继续找前面的节点,直到找到节点状态小于0的,然后设置为signal,并设置为新节点的pre。然后阻塞当前线程。
5、当调用unlock时,会对state变量减1(考虑重入情况),当state==0时,再设置exclusiveOwnerThread==null。然后对队列头节点线程唤醒。通过LockSupport.unpark方式。
二、公平锁的加锁过程:
1、线程调用lock方法时,不会去尝试获取锁,判断state是否为0,如果不为0,则判断当前线程是否与exclusiveOwnerThread线程一样(可重入性),一样则返回true,如果state==0, 且队列是空的,则会尝试获取锁。获取成功,则返回true,执行业务。
如果获取锁失败或队列不是空。则创建一个新节点node,然后如队列。与非公平锁流程类似。
参考一些优秀解析:
https://www.cnblogs.com/waterystone/p/4920797.html
https://blog.csdn.net/fuyuwei2015/article/details/83719444