JUC ReentrantLock原理

常用方法

lock()

尝试去竞争锁,竞争到了则可以执行,竞争不到,则加入到Node队列中排队等待执行。在公平锁和非公平锁中实现大致相同,主要是在竞争的时候有所不同。

其是否竞争到主要是依据AQS中的变量state,用0代表无锁状态,哪个线程通过cas的方式把state从0改变了,则代表当前线程竞争到锁了。

如果没有竞争到的线程,也会通过AQS中的Node双向链表进行管理,会通过Node记录线程以及Node的状态,对线程进行存储,方便后续在竞争到锁的节点释放时进行唤醒后续线程。

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

tryLock()

尝试去竞争锁,竞争成功则直接占有锁。只会尝试一次。可以参考Sync内部类的方法描述。

public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

tryLock(long timeout, TimeUnit unit)

在单位时间内判断是否能获取锁。

其本质也是AQS中去尝试获取锁,如果获取不到,则通过LockSupport.park(timeout)进行按时间的阻塞。到阻塞时间没有获取到锁之后返回false,如果在规定时间内调用了unpark方法,则返回true。标识获取到锁了

public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

unlock

unlock本质就是把state状态减一,然后唤醒在链表中的等待节点

public void unlock() {
        sync.release(1);
    }

newCondition

newCondition方法主要是依托于Aqs。

其主要原理是形成单独的当前条件的Condition链表,在初始化状态时,并不在竞争锁的Node双向链表中,在达到了一定条件之后即调用signal或者signalAll方法之后会把当前节点放置到竞争锁的Node链表中再去竞争

public Condition newCondition() {
        return sync.newCondition();
    }

构造方法

ReentrantLock() 默认非公平锁

public ReentrantLock() {
        sync = new NonfairSync();
    }

public ReentrantLock(boolean fair) 

public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

内部类Sync(基于aqs的同步器)

整体思想

方法描述

nonfairTryAcquire

非公平的去获取锁,为什么说是非公平,因为没有判断前边的链表上是否有正在排队的节点。可能会出现上一个节点刚释放锁,排队的节点和当前插入的节点竞争的情况。

为什么是可重入的,因为在获取不到锁的时候判断如果是当前线程,则可以继续获取到锁。

        // 非公平的尝试获取锁
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            // 获取当前锁的状态。基于aqs的实现
            // aqs中的state会代表整体锁的情况,在ReentrantLock中state为0代表当前锁是空闲的
            int c = getState();
            if (c == 0) {
                // 如果锁是空闲的,则尝试去占有。通过cas的方式设置
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 此处为可重入的原理,如果判断线程拥有者是当前线程,则设置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;
        }

tryRelease

释放锁

其实针对ReentrantLock来说,是否上锁主要是判断state的值,释放锁也就是让累加上的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;
        }

newCondition

其主要用途是在达成某个条件之后,才会让当前对象参与竞争。通过await方法进入对应的ConditionObject链对象中,直到当前ConditionObject调用signal或者signAll方法之后,才会把当前对象放置到ReentrantLock的Node链中

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

NonfairSync(基于Sync的非公平同步器)

lock

会调用aqs的acquire方法,主要是尝试获取锁,然后再队列里竞争锁,竞争到了则执行,并且改变链表中的node头结点为当前节点。如果获取不到,则park住当前线程。

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

FairSync(基于Sync的公平同步器)

tryAcquire

尝试获取锁,但是会在获取锁的时候先判断Node链表中是否有前驱节点,没有的话,才回去竞争锁。

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值