Java中ReentrantLock与Condition协作时的线程执行逻辑疑问
关于Condition唤醒与ReentrantLock锁契约的疑问
场景
- Thread-1 对空缓冲区调用
take()方法 - Thread-2 对空缓冲区调用
put(1)方法
时间线
- t0时刻:Thread-1在第24行获取锁
- t1时刻:由于
count==0,线程进入第27行的等待逻辑,此时线程会释放锁并进入休眠状态 - t2时刻:Thread-2在put方法的第10行获取锁
- 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的锁契约,原因如下:
signal()方法的作用只是把等待在Condition上的线程转移到锁的同步队列,而非直接唤醒执行。Thread-1被唤醒后,并不会立刻恢复运行,而是进入锁的等待队列排队。- Thread-1要继续执行
take()的后续逻辑,必须重新获取ReentrantLock的锁。此时Thread-2还持有锁,所以Thread-1只能在同步队列中等待,直到Thread-2执行lock.unlock()释放锁后,才有机会竞争锁资源。 - ReentrantLock“同一时间仅一个线程持有锁”的规则自始至终都被遵守:Thread-2持有锁期间,Thread-1无法获取锁执行;只有当Thread-2释放锁后,Thread-1才能尝试获取锁并继续执行。
内容的提问来源于stack exchange,提问作者Novice User
相关产品推荐
相关产品推荐

