【问题标题】:Java - Reentrant Lock, can't access newly created ConditionJava - 可重入锁,无法访问新创建的条件
【发布时间】:2013-04-06 22:15:42
【问题描述】:

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

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

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

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();
    }
}

有什么想法吗?

干杯

【问题讨论】:

  • 无一例外只是无限期的停顿
  • 不可能有 2 个不同的 Chopstick 实例并且信号发生在与等待不同的实例上?
  • 嗯,有一个 ArrayList ,其中两个筷子被传递给另一个类,该类使用它的pickupLeftChopstick() 方法,该方法又调用了Chopstick 类中的pickUpChopstick() 方法。
  • @mgibson - 您是否在与您的主逻辑运行位置分开的线程中调用您的pickupChopstick 方法?否则,您将完全锁定自己。

标签: java concurrency locking conditional-statements reentrantlock


【解决方案1】:

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();
    }
  }
}

这是一个使用 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();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多