ReentrantLock分析

本文详细介绍了JavaReentrantLock中的公平锁和非公平锁机制,以及它们如何基于AbstractQueuedSynchronizer(AQS)实现并发控制。ReentrantLock的核心在于Sync内部类,公平锁在加锁时考虑等待队列,而非公平锁则优先抢占。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ReentrantLock是常用的控制并发安全的lock实现了,里面主要包含lock()加锁方法,unlock()释放锁的方法,内部又分为公平锁和非公平锁,简单看下怎么实现的吧
简单提下lock自己平时怎么用的

// 这里的lock注意,需要用的是同一个lock才能保证并发安全
ReentrantLock reentrantLock = new ReentrantLock();

reentrantLock.lock();
// 自己业务代码放在这里

reentrantLock.unlock();

Sync 内部类

abstract static class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = -5179523762034025860L;

    /**
     * Performs non-fair tryLock.  tryAcquire is implemented in
     * subclasses, but both need nonfair try for trylock method.
     */
    @ReservedStackAccess
    final boolean nonfairTryAcquire(int acquires) {
        // 非公平锁的加锁
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            // state为0 的时候代表没人持有,那么就cas尝试加锁
            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;
    }
 @ReservedStackAccess
    protected final boolean tryRelease(int releases) {
        // 释放锁
        int c = getState() - releases;
        // 不是自己持有的话,异常
        if (Thread.currentThread() != getExclusiveOwnerThread())
            throw new IllegalMonitorStateException();
        boolean free = false;
        // 如果为0,证明释放了
        if (c == 0) {
            free = true;
            setExclusiveOwnerThread(null);
        }
        // 更新state
        setState(c);
        return free;
    }
	// 是不是自己持有的锁
    protected final boolean isHeldExclusively() {
        // While we must in general read state before owner,
        // we don't need to do so to check if current thread is owner
        return getExclusiveOwnerThread() == Thread.currentThread();
    }

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

    // Methods relayed from outer class
    // 获取持有者,如果没人持有就是null
    final Thread getOwner() {
        return getState() == 0 ? null : getExclusiveOwnerThread();
    }

    // 被持有了多少次
    final int getHoldCount() {
        return isHeldExclusively() ? getState() : 0;
    }

    // 是不是正在锁
    final boolean isLocked() {
        return getState() != 0;
    }

    /**
     * Reconstitutes the instance from a stream (that is, deserializes it).
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        setState(0); // reset to unlocked state
    }
}

Sync 主要定义了锁的一些常用操作,可以看到它继承了AbstractQueuedSynchronizer,这里才是重要的,这里后面单独文章分析下,然后公平锁和非公平锁继承Sync,差别就在于加锁这点


/**
 * Sync object for non-fair locks
 */
static final class NonfairSync extends Sync {
    private static final long serialVersionUID = 7316153563782823691L;
    protected final boolean tryAcquire(int acquires) {
        // 非公平锁,直接使用的父类的
        return nonfairTryAcquire(acquires);
    }
}

/**
 * Sync object for fair locks
 */
static final class FairSync extends Sync {
    private static final long serialVersionUID = -3000897897090466540L;
    /**
     * Fair version of tryAcquire.  Don't grant access unless
     * recursive call or no waiters or is first.
     */
    @ReservedStackAccess
    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;
    }
}

总结

可以看到ReentrantLock里面主要就是内部类提供了公平锁和非公平锁,然后Sync继承了AbstractQueuedSynchronizer 使用其方法,ReentrantLock 主要提供了加锁和解锁的方法,分为公平锁和非平平锁,默认非公平锁,两者的区别在于,公平锁在加锁之前会判断是不是又线程在队列里面等待,有等待的就自己排队,无等待者的话自己尝试加锁,非公平锁是看到锁处于无锁,就会cas尝试下加锁,这就是两者差别,然后通过state记录持有锁的数量,等到时候进行释放,为0的时候就是无锁了,把对应状态改为无锁,这里主要就是对AQS的应用,原理层面我们还是去分析下AQS。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值