【问题标题】:Java - Call wait() on an object and then allow object access to methodJava - 在对象上调用 wait(),然后允许对象访问方法
【发布时间】:2013-04-20 12:16:26
【问题描述】:

我有一个以线程为参数的方法。我希望这个方法能够让一个线程等待,如果没有一个线程等待,然后在另一个线程进入该方法时唤醒,以便它们两个可以交互。我想我已经接近了,但是在第一个线程上调用 wait() 之后,没有其他线程可以访问该方法。这是我的代码的极简版本:

// In the class 'Node'
public synchronized void trade(Thread thread)
{
    if (!threadWaiting)
    {
        threadWaiting = true;
        synchronized(thread)
        {
             try {
                 thread.wait();
             } catch (InterruptedException e) {...}
        }
    }
}

对于遗漏任何明显的东西,我深表歉意,我一直在寻找答案,但我是线程新手,所以我不知道要寻找什么。

所以我的问题是,当另一个线程尝试进入 trade() 时,他们不能,调试器就停在那里。

编辑: 这是我要问的更多说明。恐怕我在原始帖子中不太清楚。

所以我有一个名为 Node 的类和另一个名为 Bot 的类。 Bot 扩展线程以便它可以暂停。在程序开始时,会创建多个 Bot 对象并启动,然后每个 Bot 将调用 Node 的 trade() 方法并将自身传递给该方法。如果 Bot 是方法中的第一个,那么我希望它的线程在节点上等待,直到另一个 Bot 出现(等待的 Bot 将存储在节点中),此时两个 Bot 将交互。 下面是我的伪代码方法的更清晰示例:

// Variable to hold the bot that is waiting.
private Bot waitingBot = null;
// Method belonging to Node.
public synchronized void trade(Bot currentBot)
{
    if (waitingBot == null)
    {
        waitingBot = currentBot;
        waitingBot.wait();
    }
    else
    {
        currentBot.interactWith(waitingBot);
        waitingBot.notify();
        waitingBot = null;
    }
}

对不起,我原来的帖子的措辞。

【问题讨论】:

标签: java multithreading concurrency wait


【解决方案1】:

您的实现存在缺陷。您正在锁定传递的参数,这对于所有线程都是不同的,因此它们无法与等待通知交互。

编辑:我不确定您的目标到底是什么,但根据详细信息,这可能会有所帮助: EDIT2:添加了 lock()

private final Lock lck = new ReentrantLock();
private final Condition cnd = lck.newCondition();
private final AtomicBoolean threadwaiting = new AtomicBoolean(false);

public synchronized void trade(Thread thread)
{
    lck.lock();
    try{
    if(threadwaiting.get()){
      cnd.signalAll();
      threadwaiting.set(false);
      //perform your task
    }else{
      cnd.await();
      threadwaiting.set(true);
    }
    }
    } finally {
   lck.unlock()
 }

}

编辑: 查看您更新的帖子,您应该使用计数为 2 的 cyclicbarrier,然后这应该可以为您解决所有问题。

【讨论】:

  • 这不起作用,我仍然得到相同的结果。我已经用更多信息更新了我的答案,因为我可能对自己的解释不够清楚。
【解决方案2】:

这是一个死锁,因为当你调用thread.wait(); 时你释放了线程对象锁。但是this对象锁在同步方法上仍然存在,这就是为什么其他人不能进入它。

【讨论】:

    【解决方案3】:

    类似于 loki 的代码,但有所改进

    private final Lock lock = new ReentrantLock();
    private final Condition cnd = lock.newCondition();
    private final AtomicBoolean threadwaiting = new AtomicBoolean(false);
    
    public void trade(Thread thread) {
        lock.lock();
    
        if (threadwaiting.get()) {
            cnd.signalAll();
            lock.unlock();
            // perform your task of second thread
        } else {
            threadwaiting.set(true);
            try {
                cnd.await();
                // perform your task of first thread
            } catch (InterruptedException e) {
            } finally {
                threadwaiting.set(false);
                lock.unlock();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-12
      • 1970-01-01
      • 2010-10-01
      • 1970-01-01
      相关资源
      最近更新 更多