Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
174 views
in Technique[技术] by (71.8m points)

multithreading - Java Wait and Notify: IllegalMonitorStateException

I don't completely understand how wait and notify (of Object) work, and as a result I'm forced to slim down my attempts into the following section of code.

Main.java:

import java.util.ArrayList;

class Main
{
  public static Main main = null;

  public static int numRunners = 4;
  public static ArrayList<Runner> runners = null;

  public static void main(String[] args)
  {
    main = new Main();
  }

  Main()
  {
    runners = new ArrayList<Runner>(numRunners);

    for (int i = 0; i < numRunners; i++)
    {
      Runner r = new Runner();
      runners.add(r);
      new Thread(r).start();
    }

    System.out.println("Runners ready.");
    notifyAll();
  }
}

Runner.java:

class Runner implements Runnable
{
  public void run()
  {
    try
    {
      Main.main.wait();
    } catch (InterruptedException e) {}
    System.out.println("Runner away!");
  }
}

Currently I get an IllegalMonitorStateException when calling Main.main.wait();, but I don't understand why. From what I can see, I need to synchronize Runner.run, but in doing so I assume it would only notify one thread, when the idea is to notify them all.

I've looked at java.util.concurrent, but I can't find a suitable replacement (maybe I'm just missing something).

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can't wait() on an object unless the current thread owns that object's monitor. To do that, you must synchronize on it:

class Runner implements Runnable
{
  public void run()
  {
    try
    {
      synchronized(Main.main) {
        Main.main.wait();
      }
    } catch (InterruptedException e) {}
    System.out.println("Runner away!");
  }
}

The same rule applies to notify()/notifyAll() as well.

The Javadocs for wait() mention this:

This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.

Throws:

IllegalMonitorStateException – if the current thread is not the owner of this object's monitor.

And from notify():

A thread becomes the owner of the object's monitor in one of three ways:

  • By executing a synchronized instance method of that object.
  • By executing the body of a synchronized statement that synchronizes on the object.
  • For objects of type Class, by executing a synchronized static method of that class.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...