ReentrantLock和AbstractQueuedSynchronizer的分析
从ReentrantLock到AQS的分析
ReentrantLock的主要方法:
1、lock():获取锁,没获取到会阻塞(Sync定义的抽象方法)
2、unLock():释放锁(ReentrantLock定义的方法)
3、tryLock():内部调用nonfairTryAcquire(1)以非公平的方式尝试获取锁,不会阻塞
4、tryLock(long timeout, TimeUnit unit):调用各自重写的tryAcquire()方法来尝试获取锁,也会到队列排队,超过等待时间没获取到会中断等待
5、newCondition():设置条件锁,唤醒的时候可以根据条件来唤醒对应的锁
6、lockInterruptibly():可中断锁;持有该锁的线程或者在等待该锁的线程可以被中断
ReentrantLock可以实现公共锁和非公平锁,内部类Sync继承AQS来实现主要功能;
AQS主要是通过CAS+volatile int state标识+双向链表构成的先进先出队列实现获取锁、释放锁和等待锁的过程,ReentrantLock也遵循这一核心;
ReentrantLock的非公平锁:
非公平锁的获取:state=0(没有线程拥有锁),这时先尝试获取锁,没有获取到的话再进入队列排队
// 默认为非公平锁 public ReentrantLock() { sync = new ReentrantLock.NonfairSync(); } static final class NonfairSync extends ReentrantLock.Sync { /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { // 与公平锁的不同之处,会先试着抢占锁,没抢到再排队等待 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else // 进入队列排队,等待获得锁 acquire(1); } // 注意:子类重写了AQS的tryAcquire()方法,子类调用是调用自己的 // 公平锁和非公平锁的tryAcquire()不一样 protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } // 非公平锁的tryAcquire()方法 final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // 和公平锁的不同之处,不会先判断队列里面是否有线程在等待,而是直接去抢占锁 if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { // 可重入 int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
ReentrantLock的公平锁:
公平锁获取:state=0(没有线程拥有锁),这时判断队列是否有线程在等待,如果有的话则直接进入队列排队
// 设置是公平锁还是非公平锁 public ReentrantLock(boolean fair) { sync = fair ? new ReentrantLock.FairSync() : new ReentrantLock.NonfairSync(); } static final class FairSync extends ReentrantLock.Sync { final void lock() { // 这里不会像非公平锁一样先尝试获取锁,而是队列中如果有等待线程,则直接进入队列排队 acquire(1); } // 公平锁的tryAcquire() protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // 公平锁在state=0(没有线程持有锁)的时候,会先去判断等待队列里面是否有线程再排队,使用hasQueuedPredecessors()来判断 // 如果有线程在排队则不能获取到锁 // compareAndSetState(0, acquires) CSA原子更新 if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { // 当前线程可以获得锁,设置当前线程为锁的拥有者 setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { // 此处,线程处于重入状态 int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); // 上面的compareAndSetState和setState的区别: // 上面线程还没有获得锁,无法保证线程安全,所以会调用unsafe.compareAndSwapInt()来保证state更新的原子性 // 这里的线程已经获的了锁,是线程安全的,可以直接修改state的值 setState(nextc); return true; } return false; } }