一尘不染

在可重入锁中等待条件

java

以下代码取自的JavaDocCondition

class BoundedBuffer {
  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(Object 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 Object take() throws InterruptedException {
    lock.lock();
    try {
      while (count == 0) 
        notEmpty.await();
      Object x = items[takeptr]; 
      if (++takeptr == items.length) takeptr = 0;
      --count;
      notFull.signal();
      return x;
    } finally {
      lock.unlock();
    }
  } 
}

想象一下, 消费者生产者这 两个线程,一个正在使用take,一个put在单个实例上BoundedBuffer

假设 消费者 先运行take(),然后锁定,lock然后循环运行notEmpty.await();

现在, 生产者 如何才能put()通过锁定lock已由 消费者 持有的来进入方法?

我在这里想念什么?是lock线程正在等待其条件之一时“临时释放”吗?锁的重新 进入 到底意味着什么?


阅读 180

收藏
2020-12-03

共1个答案

一尘不染

双方Locksynchronized允许一个线程等待的时候,另一个线程可以获得锁放弃锁。要停止等待,线程必须重新获取锁。

注意:它们没有完全释放它,并且如果您进行堆栈跟踪,则可能有多个线程似乎同时持有该锁,但其中最多一个线程将在运行(其余线程将被阻塞)

Condition.await()

与此条件相关联的锁被原子释放,并且出于线程调度目的,当前线程被禁用,并且处于休眠状态,直到发生以下四种情况之一:

  • 其他一些线程为此条件调用signal()方法,并且当前线程恰好被选择为要唤醒的线程;要么
  • 其他一些线程为此条件调用signalAll()方法。要么
  • 其他一些线程中断当前线程,并支持中断线程挂起;要么
  • 发生“虚假唤醒”。

在所有情况下,在此方法可以返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,可以保证保持此锁

2020-12-03