java.lang.IollegalMonitorStateException调用signal()时出现trhown



我在一个多线程程序中工作。线程在矩阵(workerThread)中工作,我有一个打印矩阵状态的线程(display)。我在monitor.signal()行的matrix类的increaseRow()中得到了这个异常。

有人能告诉我,怎么了?

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

显示类别:

    public class Display extends Thread {
        private Matrix matrix;
        public Display(Matrix matrix) {
            this.matrix = matrix;
        }
        @Override
        public void run() {
            while(true)
            matrix.printMatrix();
        }
    }

workerThread类:

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

更新

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

是的,问题是在increaseRow中调用monitor.signal()时没有首先锁定lock。来自Condition.signal():的文档

当调用此方法时,实现可能(通常确实)要求当前线程持有与此Condition相关联的锁。实现必须记录此前提条件以及在未持有锁的情况下所采取的任何操作。通常,会抛出一个异常,例如IllegalMonitorStateException

您的increaseRowincreaseColumn方法都应该具有的结构

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

就像sumRowsumColumnprintMatrix方法一样。或者,您可能希望为每行和每列都有一个单独的监视器(和条件)。你基本上需要考虑所有的并发约束——如果没有更多的想法,很难给出更多的指导。

在方法increaseRow(int)increaseColumn(int)中,您需要在lock上持有一个锁,否则您无法调用monitor.signal()

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

来自信号的文档

当调用此方法时,实现可能(通常确实)要求当前线程持有与此Condition相关联的锁。

然后对于再入锁定:

如果在调用任何Condition等待或信令方法时未持有此锁,则会引发IllegalMonitorStateException。

相关内容

最新更新