Java.lang.IllegalMonitorStateException trhown when calling signal ()

i runs in a multithreaded program. The threads are running in a matrix (workerThread), and I have a thread (display) that prints the matrix state. Getting this exception, inside the scaleRow () class of the Matrix class on the monitor.signal () line

can someone tell me what is wrong?

public class Matrix {

    private int row;
    private int column;

    private int[][] matrix;
    private Map<Integer, String> mapForRow;
    private Map<Integer, String> mapForColumn;

    private Lock lock;
    private Condition condition;
    private Condition monitor;

    private boolean rowIncreased;
    private boolean columnIncreased;
    private boolean columnCanBeAdded;
    private boolean rowCanBeAdded;
    private boolean print;

    public Matrix(int row, int column) {
        this.matrix = new int[row][column];
        lock = new ReentrantLock();
        mapForColumn = new LinkedHashMap<Integer, String>();
        mapForRow = new LinkedHashMap<Integer, String>();
        condition = lock.newCondition();
        monitor = lock.newCondition();
        rowIncreased = false;
        columnIncreased = false;
        rowCanBeAdded = false;
        columnCanBeAdded = false;
        print = false;
    }

    public void increaseRow(int row) {
        if (!mapForRow.containsKey(row))
            mapForRow.put(row, "not increased");
        if (mapForRow.get(row).equals("not increased") && !columnIncreased) {
            mapForRow.get(row).equals("increased");
            rowIncreased = true;
            for (int j = 0; j < matrix.length; j++)
                setMatrix(row, j, matrix[row][j] + 1);
            mapForRow.put(row, "not increased");
            rowIncreased = false;
            print = true;
            monitor.signal();
        }
    }

    public void increaseColumn(int column) {
        if (!mapForColumn.containsKey(column))
            mapForColumn.put(column, "not increased");
        if (mapForColumn.get(column).equals("not increased") && !rowIncreased) {
            mapForColumn.get(column).equals("increased");
            columnIncreased = true;
            for (int i = 0; i < matrix.length; i++)
                setMatrix(i, column, matrix[i][column] + 1);
            mapForColumn.put(column, "not increased");
            columnIncreased = false;
            print = true;
            monitor.signal();
        }
    }

    public int sumColumn(int column) {
        lock.lock();
        int sum = 0;
        try {
            columnCanBeAdded = false;
            while (columnIncreased || rowIncreased || rowCanBeAdded) {
                condition.await();
            }
            for (int i = 0; i < matrix.length; i++)
                sum += matrix[i][column];
            columnCanBeAdded = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        condition.signalAll();
        print = true;
        monitor.signal();
        return sum;
    }

    public int sumRow(int row) {
        lock.lock();
        int sum = 0;
        try {
            rowCanBeAdded = false;
            while (columnIncreased || rowIncreased || columnCanBeAdded) {
                condition.await();
            }
            for (int j = 0; j < matrix.length; j++)
                sum += matrix[row][j];
            rowCanBeAdded = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        condition.signalAll();
        print = true;
        monitor.signal();
        return sum;
    }

    public void printMatrix() {
        lock.lock();
        try {
            while (!print) {
                monitor.await();
            }
            System.out.println("begin print matrix");
            for (int i = 0; i < row; i++) {
                System.out.println();
                for (int j = 0; j < column; j++)
                    System.out.print(matrix[i][j]);
            }
            System.out.println("end print matrix");
            print = false;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

    public void setMatrix(int row, int column, int number) {
        matrix[row][column] = number;
    }

    public static void main(String[] args) {
        Matrix matrix = new Matrix(10, 10);
        for (int i = 0; i < 10; i++)
            for (int j = 0; j < 10; j++)
                matrix.setMatrix(i, j, 0);
        for (int i = 0; i < 10; i++) {
            WorkerThread workerThread = new WorkerThread(matrix);
            workerThread.start();
        }
        // print the matrix state
        Display display = new Display(matrix);
        display.start();

    }
}

      

display class:

    public class Display extends Thread {

        private Matrix matrix;

        public Display(Matrix matrix) {
            this.matrix = matrix;
        }

        @Override
        public void run() {
            while(true)
            matrix.printMatrix();
        }

    }

      

workerThread class:

public class WorkerThread extends Thread {

    private Matrix matrix;

    public WorkerThread(Matrix matrix) {
        this.matrix = matrix;
    }

    @Override
    public void run() {
        // prevent thread to die
        while (true) {
            matrix.increaseColumn(new Random().nextInt(9));
            matrix.increaseRow(new Random().nextInt(9));
            try {
                sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            matrix.sumRow(new Random().nextInt(9));
            matrix.sumColumn(new Random().nextInt(9));
        }
    }

}

      

UPDATE

Exception in thread "Thread-7" Exception in thread "Thread-6" Exception in thread "Thread-4" Exception in thread "Thread-1" Exception in thread "Thread-5" Exception in thread "Thread-9" Exception in thread "Thread-0" Exception in thread "Thread-2" Exception in thread "Thread-3" Exception in thread "Thread-8" java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signal(AbstractQueuedSynchronizer.java:1941)
    at Matrix.increaseColumn(Matrix.java:67)
    at WorkerThread.run(WorkerThread.java:15)
java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signal(AbstractQueuedSynchronizer.java:1941)
    at Matrix.increaseColumn(Matrix.java:67)
    at WorkerThread.run(WorkerThread.java:15)begin print matrix
end print matrix

      

+3


source to share


2 answers


Yes, the problem is that increaseRow

you are calling monitor.signal()

without blocking lock

. From the documentation for Condition.signal()

:

An implementation can (and usually) require the current thread to hold the lock associated with this Condition when this method is called. Implementations should document this precondition and any action taken if the lock is not held. Typically, an exception is thrown such as IllegalMonitorStateException

.

Both methods increaseRow

and increaseColumn

must have a structure



lock.lock();
try {
    // code including monitor.signal() here
} finally {
    lock.unlock();
}

      

how your methods do it sumRow

, sumColumn

and printMatrix

. In addition, you can have a separate monitor (and conditions) for each row and for each column. You basically need to consider all your concurrency constraints - it's hard to give more guidance without thinking about what you're trying to achieve.

+6


source


In methods increaseRow(int)

and increaseColumn(int)

you need to lock the lock on lock

, otherwise you cannot callmonitor.signal()

lock.lock();
try {
     ....
     monitor.signal();
} finally {
    lock.unlock();
}

      

From the docs for signal



An implementation can (and usually) require the current thread to hold the lock associated with this Condition when this method is called.

and then for ReentrantLock :

If this lock is not held when any of the wait or signaling methods are called, then an IllegalMonitorStateException is thrown.

+4


source







All Articles