ReenTranLock底层原理

ReenTranLock底层原理

ReenTranLock是一种可重入锁,比synchronized方便是因为内部还有condition可以将锁进行分离唤醒,内部提供lock和unlock这两个核心方法

lock调用的是sync中lock方法,在公平和非公平下有各自实现

在这里插入图片描述

  • 公平模式的lock方法:

    直接调用acquired

    final void lock() {
        acquire(1);
    }
    

    公平模式重写tryAcquire方法

            protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    //如果头和尾一样或如果头结点的下一个保存的thread为当前的线程
                    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;
            }
    
  • 非公平模式的lock方法:

    final void lock() {
        //将state使用cas设置为1,如果成功,将当前的exclusiveOwnerThread设置为当前线程
        if (compareAndSetState(0, 1))
          setExclusiveOwnerThread(Thread.currentThread());
        else
        //否则执行AQS的acquire方法
        acquire(1);
    }
    

    AQS的acquired方法:

    public final void acquire(int arg) {
        //公平调用重写的tryAcquire,非公平调用非公平模式的nonfairTryAcquire(1)方法
        if (!tryAcquire(arg) &&
            //生成队尾并插入队列尾部获取节点后执行acquireQueued方法去阻塞
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // 放入队列尾部
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        //如果尾部是空,执行enq去新建立一个头和尾
        enq(node);
        return node;
    }
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                //获取当前结点的前驱节点
                final Node p = node.predecessor();
                //如果前驱是头并且执行nonfairTryAcquire成功
                if (p == head && tryAcquire(arg)) {
                    //将头结点设置为当前结点
                    setHead(node);
                    //之前头结点回收
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                //第一调用会返回false将p的Status变为SIGNAL,第二进来会调用parkAndCheckInterrupt执行lockSupport的park()方法等待唤醒
                if (shouldParkAfterFailedAcquire(p, node) &&
                    //调用park方法进行阻塞
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
    

    nonfairTryAcquire方法:

            final boolean nonfairTryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                //可重入的实现,上面cas将state无法变为1的话,这边判断exclusiveOwnerThread是否是当前线程,如果是state继续往上
                //加一
                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;
            }
    
  • unlock方法实现

        public final boolean release(int arg) {
            //如果更改成功
            if (tryRelease(arg)) {
                Node h = head;
                if (h != null && h.waitStatus != 0)
                    //唤醒clh队列中的下一个node
                    unparkSuccessor(h);
                return true;
            }
            return false;
        }
    

    调用的是tryRelease方法和unparkSuccessor

    tryRelease方法将state变量变为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;
            }
    

    接着调用unparkSuccessor:

    private void unparkSuccessor(Node node) {
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);
        //获取下一个节点
        Node s = node.next;
        //如果下个节点不是SIGNAL状态会从尾部开始找前驱为SIGNAL状态的去唤醒
        if (s == null || s.waitStatus > 0) {
            s = null;
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        //下一个节点是signal状态会调用unpark
        if (s != null)
            LockSupport.unpark(s.thread);
    }
    

    非公平模式和公平模式最根本的不同是非公平是下尝试cas改变state为1再去调用acquire加入clh队列

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值