Joseph Little
Joseph Little

Reputation: 931

Java - Call wait() on an object and then allow object access to method

I have this method which takes a thread as a parameter. I want this method to be able to make a thread wait if there is not one waiting already and then wake up when another thread comes into the method so that the two of them can interact. I think I'm close but after I call wait() on the first thread no other threads can gain access to that method. Here is a minimalist version of my code:

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

I apologise for missing anything obvious, I've been looking around for an answer but I'm new to threading so I've no idea what to look for.

So my problem is that when another thread attempts to get into trade() they can't, the debugger just stops right there.

EDIT: Here's some more clarification on what I'm asking. I'm afraid I wasn't too clear in my original post.

So I have one class called Node and another class called Bot. Bot extends thread so that it can be paused. At the start of the program multiple Bot objects are created and are then started, each Bot will then call the trade() method of the Node and pass itself to the method. If a Bot is the first in the method then I want its thread to wait on the Node until another Bot comes along (The waiting Bot will be stored in the Node), at which point the two Bots will interact. Below is a clearer example of my method in pseudo code:

// 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;
    }
}

Sorry about the wording of my original post.

Upvotes: 3

Views: 1053

Answers (3)

Lokesh
Lokesh

Reputation: 7940

Your implementation has a flaw. You are taking lock on parameter passed which will be different for all Threads so they can't interact with wait notify.

EDIT: I am not sure what exactly your aim is but based on details this might help: EDIT2: Added 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()
 }

}

EDIT: Looking at your updated post , you should use cyclicbarrier with count 2 then that should solve it all for you.

Upvotes: 1

johnchen902
johnchen902

Reputation: 9601

It's like loki's code, but improved

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

Upvotes: 0

Mikhail
Mikhail

Reputation: 4223

This is a dead lock, because when you call thread.wait(); you release thread object lock. But this object lock on synchronized method remains, that's why no one else can enter it.

Upvotes: 0

Related Questions