在重入锁定的条件下等待

vek*_*tor 28 java synchronization

以下代码取自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();
    }
  } 
}
Run Code Online (Sandbox Code Playgroud)

想象一下2个线程,ConsumerProducer,一个使用take,一个put在单个实例上BoundedBuffer.

让我们说消费者先行,take()然后他会锁定lock并且现在循环notEmpty.await();.

现在生产者怎么可能进入put()过去锁定的方法lock,消费者已经持有?

我在这里错过了什么?lock当线程正在等待其中一个条件时,"暂时释放"吗?那锁的重入是什么意思呢?

Pet*_*rey 28

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

注意:它们不会完全释放它,如果你采用堆栈跟踪,你可以有多个线程,它们似乎一次持有锁,但最多其中一个将运行(其余的将阻塞)

来自Condition.await()

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

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

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


Mar*_*nik 6

就重新入侵而言,这意味着拥有某个锁的线程可以再次重新获得相同的锁.如果不是这样,则synchronized方法将无法调用synchronized同一对象的另一个方法.

重新参与不涉及对您的问题的理解.