执行流程分析

公平锁加锁

调用FairSync包下的lock方法, 调用AQS包下的acquire方法

/*ReentrantLock*/
final void lock() {
            acquire(1); //用于以独占模式获取锁,并通过调用至少一次 tryAcquire 方法来获取锁。如果获取锁失败,线程将被排队,并可能重复阻塞和解除阻塞,
        }
/*AQS*/
    public final void acquire(int arg) {   // 这里如果是reentrantlock的话,是调用的ReentrantLock的重写方法的,不是此类中直接点进去抛异常的那个类
        if (!tryAcquire(arg) &&     // 调用 tryAcquire 方法来尝试以独占模式获取锁。如果 tryAcquire 方法返回 true,表示获取锁成功,方法直接返回。
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))  //如果 tryAcquire 方法返回 false,则说明获取锁失败。接下来,调用 addWaiter(Node.EXCLUSIVE) 方法将当前线程作为独占模式的等待者加入到同步队列中,并返回表示该节点的 Node 对象。
            selfInterrupt();    // 如果 acquireQueued 方法返回 true,表示当前线程已成功获取到锁,并且此时可能已经从同步队列中移除。在这种情况下,调用 selfInterrupt 方法来中断当前线程,以响应可能的中断请求。
    }

这里要注意下,tryAcquire方法调用的不是AQS包中实现的那个抛异常的方法哈!!!
而是ReentrantLock类中的FairSync下的tryAcquire

  • 调用 tryAcquire 方法来尝试以独占模式获取锁。如果 tryAcquire 方法返回 true,表示获取锁成功,方法直接返回。

  • 如果 tryAcquire 方法返回 false,则说明获取锁失败。接下来,调用 addWaiter(Node.EXCLUSIVE) 方法将当前线程作为独占模式的等待者加入到同步队列中,并返回表示该节点的 Node 对象。

    static final class FairSync extends Sync {      // 公平锁

        final void lock() {
            acquire(1); //用于以独占模式获取锁,并通过调用至少一次 tryAcquire 方法来获取锁。如果获取锁失败,线程将被排队,并可能重复阻塞和解除阻塞,
        }

        protected final boolean tryAcquire(int acquires) {      // 公平锁
            final Thread current = Thread.currentThread();      // currentThread
            int c = getState();         // 重入状态  hasQueuedPredecessors为false才继续cas,为true也就是有线程排队的话直接else if 了 ,尝试之前会利用 hasQueuedPredecessors() 方法来判断 AQS 的队列中中是否有其他线程,如果有则不会尝试获取锁(这是公平锁特有的情况)。
            if (c == 0) {         // 首先进入hasQueuedPredecessors方法中,判断当前队列是否有线程正在排队,当有线程正在排队时,代表锁还在被释放的过程中,仅仅只是锁的状态码被改变,但锁没有被释放,所以线程仍需入队排队
                if (!hasQueuedPredecessors() &&                 //  当进入hasQueuedPredecessors方法中,发现没有线程正在排队时,代表锁此时并没有被人持有,此时可以尝试CAS操作获取锁,当获取成功,tryAcquire方法返回true,线程继续执行
                    compareAndSetState(0, acquires)) {      // cas自旋
                    setExclusiveOwnerThread(current);               // 设置当前线程独占
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {    // 锁重入,当前线程有权限,再次进入
                int nextc = c + acquires;                       // nextc自增
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);                                // 设置state, state标识着重入锁的进行进度
                return true;
            }
            return false;                                   // 有线程在排队喽。
        }
    }
/*AQS类中的addWaiter*/
    private Node addWaiter(Node mode) {                     // 将当前线程创建节点并指定模式,加入队列中,通过cas,加入队列尾部
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {    // 这里也要cas, 这思维!!!!!
                pred.next = node;
                return node;
            }
        }
        enq(node);  // 添加成功是不会走这个方法的,不用担心,这个方法是以正常方式入队
        return node;
    }


公平锁调用了AQS类中的hasQueuedPredecessors方法
hasQueuedPredecessorsfalse才继续cas,为true也就是有线程排队的话直接else if 了 ,尝试之前会利用 hasQueuedPredecessors() 方法来判断 AQS 的队列中中是否有其他线程,如果有则不会尝试获取锁(这是公平锁特有的情况)。

    public final boolean hasQueuedPredecessors() {      // 判断当前队列是否有线程正在排队,如果存在,则返回 true,否则返回 false,表示当前线程位于队列的头部或队列为空。
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

非公平锁加锁

默认加的就是非公平锁
看是否自旋成功,自旋成功设置该线程独占,否则也调用父类AQSacquire() , acquire中调用的是子类重写的tryAcquire(),而不是父类的直接抛异常的tryAcquire

    static final class NonfairSync extends Sync {       // 非公平锁
        final void lock() {
            if (compareAndSetState(0, 1))           // cas
                setExclusiveOwnerThread(Thread.currentThread());    // 自旋成功则设置该线程占有
            else
                acquire(1);     // 调用父类AQS的acquire() , acquire中调用的是子类重写的tryAcquire(),而不是父类的直接抛异常的tryAcquire
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);                 // 调用的129行的,nonfairTryAcquire 加非公平锁
        }
    }

可以看到非公平锁的tryAcquire方法调用了Sync类的nonfairTryAcquire

    abstract static class Sync extends AbstractQueuedSynchronizer {             // 继承了aqs
        abstract void lock();

        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();  // 当前线程
            int c = getState();                             // 获取state 是volitale的
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {  // cas 期待原值是0,是0才能塞入
                    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*/
    public void unlock() {
        sync.release(1);
    }
/*AQS*/
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
/*ReentrantLock*/
// tryRelease方法调用的是ReentrantLock类的Sync内部类的tryRelease
        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;                                    // ret
        }

小结

其中多处用到了模板模式,
acquire()中使用了模板模式,调用子类的tryAcquire()尝试获取锁,如果tryAcquire()返回false,则进入等待队列自旋获取,再判断前驱的waitStatus,判断是否需要被阻塞等。
release也是用到模板模式,调用子类的tryRelease

else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                //可以看出源码设计者的周到,考虑到了锁溢出的情况
                if (nextc < 0) 
                    throw new Error("Maximum lock count exceeded");
                //将当前线程持有的锁+1
                setState(nextc);
                return true;
            }

参考文献

知乎 ReentrantLock源码分析
强大的AI小助手

分类: java

0 条评论

发表评论

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注

ICP备案号: 辽ICP备20003309号