good_evening
good_evening

Reputation: 21759

Notifying two threads at the same time

How can I notify Thread t1 and Thread t2 at the same time (so it is the same probability to get hey 1 as hey2 first)? I've tried notifyAll, but couldn't make it work.

class Thr extends Thread
{
    Thr () throws InterruptedException
    {
        Thread t1 = new Thread() {
            public synchronized void run()
            {
                while (true)
                {
                    try {
                        wait();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    try
                    {
                        Thread.sleep(1500);
                    } catch (Exception e) { }
                    System.out.println("hey 1");
                }
            }
        };

        Thread t2 = new Thread() {
            public synchronized void run()
            {
                while (true)
                {                    
                    try {
                        wait();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    try
                    {
                        Thread.sleep(1500);
                    } catch (Exception e) { }
                    System.out.println("hey 2");
                }
            }
        };

        t1.start();
        t2.start();
    }

    public static void main(String args[]) throws InterruptedException
    {
        new Thr();
    }
}

Upvotes: 0

Views: 206

Answers (4)

rock_win
rock_win

Reputation: 755

If you are using Java versions greater than 1.4, then it would greatly simplyfy your task by using any of the concurrent locks:

java.util.concurrent.locks specially the ReadWrite type.

For now for message passing to all the threads at the same type - implement Observer Pattern

Upvotes: 0

Stephen C
Stephen C

Reputation: 719729

The right way to do this is to use notifyAll. The real problem with your code seems to be that you have two threads waiting for notifications on different mutexes. You need them to wait on a single object ... as described in @ShyJ's answer.


Note that there is NO WAY that you can code this so that the notification is guaranteed to be delivered first to either thread with equal probability:

  • The Java threading specs make no guarantees of fairness in wait / notify.

  • The thread scheduler implemented (typically) at the OS-level (typically) makes no such guarantees either.

The point is that the application has no control over this. The best approach is to just let wait/notifyAll do what they normally do, and design your application so that any bias in the thread scheduling does not affect the application's behaviour in an important way.

(FWIW, the usual problem is that people explicitly or implicitly assume non-randomness ... and get burned when threads get scheduled in an unexpectedly random order.)

Upvotes: 1

Brian
Brian

Reputation: 17329

I highly recommend avoiding the use of wait/notify and use something more robust. The problem is that using wait/notify in any combination will likely result in a race condition.

The only way to give equal probability to them academically is to create two Semaphore objects, have the threads try to acquire them, and use Random to choose which one to release first. Even then, if the scheduler decides to run the first one that tried to obtain the lock, then you get bias there anyway, regardless of whether or not the Sempahore is fair. This forces you to wait until the first thread is done before running the second, such as via Thread.join.

Bottom line, the only way to guarantee order in a concurrent system is to force them into a single-threaded format, which throws out the whole point of having them concurrent in the first place.

Upvotes: 0

ShyJ
ShyJ

Reputation: 4650

You should wait on a shared object and use notifyAll as in:

class Thr extends Thread
{
    Thr () throws InterruptedException
    {
        final Object lock = new Object ();

        Thread t1 = new Thread() {
            public void run()
            {
                    try {
                        synchronized (lock) {
                            lock.wait();
                        }
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }

                    System.out.println("hey 1");
            }
        };

        Thread t2 = new Thread() {
            public synchronized void run()
            {
                    try {
                        synchronized (lock) {
                            lock.wait();
                        }
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }

                    System.out.println("hey 2");
            }
        };

        t1.start();
        t2.start();
        synchronized (lock) {
            lock.notifyAll ();
        }
    }

    public static void main(String args[]) throws InterruptedException
    {
        new Thr();
    }
}

Upvotes: 2

Related Questions