3

我有这个方法,它将线程作为参数。我希望这个方法能够让一个线程等待,如果没有一个线程等待,然后在另一个线程进入该方法时唤醒,以便它们两个可以交互。我想我已经接近了,但是在第一个线程上调用 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;
    }
}

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

4

3 回答 3

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 ,那么这应该可以为您解决所有问题。

于 2013-04-20T12:24:51.603 回答
0

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

于 2013-04-20T12:49:03.530 回答
0

类似于 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();
        }
    }
}
于 2013-04-20T12:29:56.473 回答