ReentrantLock上锁过程场景解析(一):无线程竞争,不入队列 | AQS源码解析

通过学习ReentrantLock来学习AQS,本文主要是公平锁的上锁过程

AQS(AbstractQueuedSynchronizer)主要属性和内部类:
·
 private transient volatile Node head; //队首
 private transient volatile Node tail;//队尾
 private volatile int state;//锁状态,加锁成功则为1,重入+1 解锁则为0
`
 public class Node{
  volatile Node prev;
  volatile Node next;
  volatile Thread thread;
 }

0. 方法入口:

    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock(true);//公平锁
        lock.lock();
        System.out.println("=====================");
        lock.unlock();
    }

进入lock方法,lsync.lock();再往下进到公平锁内部类的lock方法

    public void lock() {
        sync.lock();
    }

在这里插入图片描述

进入acquire方法(父类AQS的acquire方法),会最先调用tryAcquire方法来尝试获取锁

在这里插入图片描述

回到ReentrantLock中tryAcquire方法的实现

在这里插入图片描述

1. 场景一:无线程竞争

  • 首先获取当前线程
  • 然后获取同步器的计算器state
  • 当前场景没有线程占用,state为0,进入hasQueuedPredecessors方法(父类AQS的方法)判断当前线程要不要排队
    public final boolean hasQueuedPredecessors() {
        Node t = tail; 
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

AQS中tail、head默认初始都是null,所以h != t 直接返回false,tryAcquire方法去反了,所以执行CAS操作

if (c == 0) {
     if (!hasQueuedPredecessors() &&
         compareAndSetState(0, acquires)) {
         setExclusiveOwnerThread(current);
         return true;
     }
 }

CAS操作将state加1,就相当于加锁,然后setExclusiveOwnerThread把当前线程设置为独占锁的线程,返回true,上锁完成

2. 场景二:线程重入:

可重入:内部方法再次上锁可以上锁成功,即testMethod中可以lock成功

public class LockTest {
    private static ReentrantLock lock;

    public static void main(String[] args) {
        lock = new ReentrantLock(true);
        lock.lock();
        testMethod();
        lock.unlock();
    }

    private static void testMethod() {
        lock.lock();
        System.out.println("==================");
        lock.unlock();
    }
}

tryAcquire方法可以看出:

  • main方法中上了锁后state为1,执行后续else if的逻辑,同一个线程,所以else if的判断成立,然后将state加1
  • 返回true,上锁成功
protected final boolean tryAcquire(int acquires) {
     final Thread current = Thread.currentThread();
     int c = getState();
     if (c == 0) {
         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");
         setState(nextc);
         return true;
     }
     return false;
 }
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页