javawaitnotifyillegalmonitorstateexcep

IllegalMonitorStateException notify() and wait()


I have a problem. When I use notify() in a synchronized block I get IllegalMonitorStateException. Can anyone help me solve this problem?

I need one thread to send a char to a second thread, then this thread has to wait and second thread print this char. After that second thread wait, and first one again sends next char

Main.java:

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
public class Main extends JFrame {

    Thread t1, t2;
    Consumer con;

    public Main() {
        con = new Consumer();
        startThreads();
    }

    private synchronized void startThreads() {
        t1 = new Thread(new Producent("grudzien", con));
        t1.start();
        t2 = new Thread(con);
        t2.start();
    }

    public class Producent implements Runnable {

        String m_atom;
        char[] atoms;
        Consumer m_c;

        public Producent(String atom, Consumer c) {
            m_atom = atom;
            m_c = c;
        }

        @Override
        public void run() {
            synchronized (this) {
                atoms = m_atom.toCharArray();
                System.out.print("Tablica znaków: ");
                for (int i = 0; i < atoms.length; i++) {
                    System.out.print(atoms[i] + ", ");
                }
            }
            for (int i = 0; i < atoms.length; i++) {
                synchronized (this) {
                    con.setChar(atoms[i]);
                    t2.notify();
                    try {
                        wait();
                    } catch (InterruptedException ex) {
                        JOptionPane.showMessageDialog(null, "Blad w wait()", "Blad!", JOptionPane.ERROR_MESSAGE);
                    }
                }
            }

        }
    }

    public class Consumer implements Runnable {

        char atom;

        public void setChar(char c) {
            atom = c;
        }

        @Override
        public void run() {
            while (true) {
                synchronized (this) {
                    try {
                        wait();
                    } catch (InterruptedException ex) {
                        JOptionPane.showMessageDialog(null, "Blad w wait()", "Blad!", JOptionPane.ERROR_MESSAGE);
                    }
                    System.out.println(atom);
                    t1.notify();
                }
            }
        }
    }

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

Solution

  • you need to be the "owner of the object's monitor" to be able to call notify on it. so far your methods are all synchronized(this), yet they call notify() on other objects (that they are not synchronized on). in other words:

    synchronized(t2) {
       t2.notify();
    }
    

    and

    synchronized(t1) {
       t1.notify();
    }
    

    for a complete explanation of monitors and synchronization in java, see here, or look for similar questions here on SO, like this one - Java Wait and Notify: IllegalMonitorStateException