什么是AQS
AQS是AbstractQueuedSynchronizer即抽象队列同步器。JUC中的很多类都用到了AbstractQueuedSynchronizer。如ReentrantLock、CountDownLatch、Semaphore底层都是实现了AbstractQueuedSynchronizer
代码解析
ReentrantLock加锁
当我们使用ReentrantLock时发生了什么事呢?
ReentrantLock默认创建一个非公平所,并赋给sync;
Sync类继承了AbstractQueuedSynchronizer;点进NonfairSync
可以看到调用lock时,if会去判断state是否等于0,如果等于0,则将state设为1;并将锁的持有者设为当前线程,若state等于1,则说明当前有人在使用锁,假设现在有线程持有锁,进入acquire
点击计入tryAcquire
找到NonfairSync对tryAcquire的重写方法
点击进入nonfairTryAcquire
假设现在state大于0,说明当前有线程持有这把锁,则运行else if (current == getExclusiveOwnerThread())。判断当前线程和持有这把锁的线程是否属于同一个线程,如果属于同一个线程,则返回true。这就是ReentrantLock属于可重入锁的原因。如果state等于0,则说明当前没有线程占用该锁,将state设为1,把锁的拥有者设为当前线程。
接着进入acquire的第二个判断中的addWaiter中
这个方法将会判断当前队列是否为空,若为空,则在队列的最前面创建一个空节点node,并将排队的节点封装成一个node加入到队列中;
进入到acquireQueued中
若当前线程的前一个节点是头节点,则尝试再次获取锁,若获取失败,则进入shouldParkAfterFailedAcquire中
由于默认当前节点的前一个节点的watistatus = 0,则执行compareAndSetWaitStatus(pred, ws, Node.SIGNAL);将当前一个节点的watistatus设为Node.SIGNAL == -1,返回false
循环继续执行,继续进入到shouldParkAfterFailedAcquire,由于刚刚把当前一个节点的watistatus设为-1了,则会满足ws == Node.SIGNAL返回true
返回true后会执行parkAndCheckInterrupt
该方法使用LockSupport.park(this)将线程阻塞