谈谈对AQS的理解

AbstractQueuedSynchronizer

首先了解AQS内最核心的变量

  1. private volatile int state; 控制锁状态变量
  2. private transient Thread exclusiveOwnerThread; 是父类AbstractOwnableSynchronizer中的属性,表示当前占锁的线程
  3. 内部对象node 是用于保存线程的节点,多个节点组成队列

从ReentrantLock加锁和释放锁的过程来理解

1.调用ReentrantLock的lock()方法尝试进行加锁
以非公平锁为例

final void lock() {
	if (compareAndSetState(0, 1))
      	setExclusiveOwnerThread(Thread.currentThread());
  	else
      	acquire(1);
}

首先调用AQS的compareAndSetState方法,upsafe类的CAS方法,作用是将stateOffset与expect做比作比较。
相等就把update值赋值给stateOffset位置的值。方法返回true。
不相等,就取消赋值,方法返回false

protected final boolean compareAndSetState(int expect, int update) {
    // See below for intrinsics setup to support this
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

如果CAS操作成功,则加锁完成,并同时设置占锁线程是当前线程,如果失败则调用 acquire(1);

public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

先执行tryAcquire(1)会再次尝试加锁,先判断当前锁状态,如果无锁占用,则直接加锁,如果有在看看占锁线程是不是就是自己,如果是则重入,就是将状态status在加1,如果不是则确认加锁失败

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;
}

加锁如果失败了,会调用acquireQueued(addWaiter(Node.EXCLUSIVE), arg),将当前的线程放入队列,并中断当前线程

2.调用unlock()方法解锁
调用AQS的release方法尝试释放锁,如果锁完全释放了,并且存在等待节点的话,则通过unparkSuccessor(h)来唤醒一个等待节点来获取锁

public final boolean release(int arg) {
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

tryRelease方法就是对当前线程的线程状态 -1,直到现在状态status=0时,才会将占锁的线程完全释放。

protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值