You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中ReentrantLock与Condition协作时的线程执行逻辑疑问

关于Condition唤醒与ReentrantLock锁契约的疑问

场景

  • Thread-1 对空缓冲区调用take()方法
  • Thread-2 对空缓冲区调用put(1)方法

时间线

  1. t0时刻:Thread-1在第24行获取锁
  2. t1时刻:由于count==0,线程进入第27行的等待逻辑,此时线程会释放锁并进入休眠状态
  3. t2时刻:Thread-2在put方法的第10行获取锁
  4. t3时刻:Thread-2执行到第17行,唤醒Thread-1

问题

由于Thread-2尚未执行到第19行释放锁,t3时刻Thread-1能否执行?这是否会破坏ReentrantLock同一时间仅允许一个线程持有锁的契约?

示例代码

class BoundedBuffer<E> {
    final Lock lock = new ReentrantLock();
    final Condition notFull  = lock.newCondition(); 
    final Condition notEmpty = lock.newCondition(); 

    final Object[] items = new Object[100];
    int putptr, takeptr, count;

    public void put(E x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length)
                notFull.await();
            items[putptr] = x;
            if (++putptr == items.length) putptr = 0;
            ++count;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0)
                notEmpty.await();
            E x = (E) items[takeptr];
            if (++takeptr == items.length) takeptr = 0;
            --count;
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }
}

解答

t3时刻Thread-1不能立即执行,完全不会破坏ReentrantLock的锁契约,原因如下:

  1. signal()方法的作用只是把等待在Condition上的线程转移到锁的同步队列,而非直接唤醒执行。Thread-1被唤醒后,并不会立刻恢复运行,而是进入锁的等待队列排队。
  2. Thread-1要继续执行take()的后续逻辑,必须重新获取ReentrantLock的锁。此时Thread-2还持有锁,所以Thread-1只能在同步队列中等待,直到Thread-2执行lock.unlock()释放锁后,才有机会竞争锁资源。
  3. ReentrantLock“同一时间仅一个线程持有锁”的规则自始至终都被遵守:Thread-2持有锁期间,Thread-1无法获取锁执行;只有当Thread-2释放锁后,Thread-1才能尝试获取锁并继续执行。

内容的提问来源于stack exchange,提问作者Novice User

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:36:07