0

我创建了一个新条件chopstickFree,在我的pickUpChopstick()方法中,我正在等待锁定它,但我根本无法访问它。

通过调试我发现当它到达方法中的chopstickFree.await()行时pickUpChopstick(),它只是无限期地暂停

我不明白?构造函数中的代码只是一个不确定的尝试让它工作,但无论哪种方式,我都创建了一个新条件,向所有人发出信号,它是免费的,但我根本无法锁定它?

public class Chopstick {
    Lock lock = new ReentrantLock();

    private Condition chopstickFree = lock.newCondition();
    private Condition chopstickInUse = lock.newCondition();

    Chopstick() {
        lock.lock();
        chopstickFree.signalAll();
        lock.unlock();
    }

    // Pick up chopstick
    public void pickUpChopstick() throws InterruptedException {
        lock.lock();

        try {
            chopstickFree.await(); // ALWAYS PAUSES HERE INDEFINITELY
            chopstickInUse.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    // Release chopstick
    public void releaseChopstick() {
        lock.lock();
        chopstickFree.signal();
        lock.unlock();
    }
}

有任何想法吗?

干杯

4

1 回答 1

2

Condition#signalAll()仅向当前Condition#await()(或其朋友)中的线程发出信号,即信号不会排队等待以后的调用。

您需要另一个受锁保护的标志才能正确实现:

public class Chopstick {
  private final Lock lock = new ReentrantLock();
  private final Condition chopstickFree = lock.newCondition();
  private volatile boolean isFree = true;

  Chopstick() { /* Nothing */ }

  // Pick up chopstick
  public void pickUpChopstick() throws InterruptedException {
    lock.lock();

    try {
      while (!isFree) {
        chopstickFree.await();
      }
      isFree = false;
    } finally {
      lock.unlock();
    }
  }

  // Release chopstick
  public void releaseChopstick() {
    lock.lock();
    try {
      isFree = true;
      chopstickFree.signal();
    } finally {
      lock.unlock();
    }
  }
}

这是一个使用 a 的版本Semaphore,它的意图可能与您的原始实现更接近:

public class Chopstick {
  private final Semaphore chopsticksAvailable = new Semaphore(1);

  Chopstick() {
    // Nothing
  }

  // Pick up chopstick
  public void pickUpChopstick() throws InterruptedException {
    chopsticksAvailable.acquire();
  }

  // Release chopstick
  public void releaseChopstick() {
    chopsticksAvailable.release();
  }
}
于 2013-04-14T22:27:01.110 回答