ReentrantLock是如何实现非公平锁的?

ReentrantLock 的非公平锁实现是通过对 AQS(AbstractQueuedSynchronizer)功能的直接利用来实现的。这种锁策略允许线程在请求锁时“插队”,即使有其他线程在等待,这样可以提高系统的吞吐量。下面是 ReentrantLock 如何实现非公平锁的具体机制:

1. 非公平锁的定义

非公平锁并不严格按照线程请求的顺序来获取锁。这意味着,某个线程在锁被释放时,有可能会比那些已经在等待队列中的线程更早地获取锁。这种方式可以减少上下文切换的频率,从而提高吞吐量。

2. 实现机制

a. 继承 AQS

ReentrantLock 会继承 AQS 的子类 NonfairSync 来实现非公平锁。

b. 重写 tryAcquire 方法

NonfairSync 中,tryAcquire(int acquires) 方法的实现是关键:

static final class NonfairSync extends Sync {
    @Override
    protected boolean tryAcquire(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) // 检查计数溢出
                throw new Error("Maximum lock count exceeded");
            setState(nextc); // 更新锁计数
            return true;
        }
        // 这里是非公平性的重要体现
        // 直接尝试获得锁,而不检查是否有其他线程在等待。
        return false;
    }
}
  • 在这个实现中,tryAcquire 方法首先检查锁的状态:
    • 如果锁未被占用,线程可以直接通过 compareAndSetState 尝试获取锁。
    • 如果锁已经被当前线程占用,它可以增加锁计数(即支持重入)。
    • 如果锁被其他线程占用,则不执行任何等待队列的检查,返回 false,表示获取锁失败。
c. “插队”机制

由于非公平锁允许后续请求的线程直接尝试获取锁,因此它可能很容易在锁可用时“插队”成功。具体来说:

  • 当一个线程释放锁时,如果此时有其他线程请求锁,可能会直接在释放时被抢夺,而不必考虑当前已经在等待中的线程队列。

3. 获取锁的方法

  • 调用 lock() 方法时会调用 tryAcquire(1) 来获取锁,由于 NonfairSync 中的实现,使得在锁释放时,很可能会有后续请求的线程轻易地获取锁。

4. 总结

ReentrantLock 的非公平锁通过继承 AQS 的 NonfairSync 类来实现。这种锁机制允许线程请求“插队”,即在锁释放时可能会被未来请求的线程抢占,也就是说,非公平锁并不严格遵循 FIFO 原则。非公平锁在高并发场景中通常能提供更高的性能,因为它减少了线程上下文切换的频率,从而提高了系统的总体吞吐量。

如果你有其他问题或需要进一步探讨,请随时在评论区留言!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java奋斗者

听说打赏我的人再也不会有BUG

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值