调用 signal() 时抛出 java.lang.IllegalMonitorStateException

标签 java multithreading

我正在研究多线程程序。线程在矩阵 (workerThread) 中工作,我有一个打印矩阵状态的线程(显示)。我收到此异常,在行监视器的 Matrix 类的 increaseRow() 中.signal()

谁能告诉我,这是怎么回事?

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() 的文档:

An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called. Implementations must document this precondition and any actions taken if the lock is not held. Typically, an exception such as IllegalMonitorStateException will be thrown.

increaseRowincreaseColumn 方法都应该有一个结构

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

就像您的 sumRowsumColumnprintMatrix 方法一样。或者,您可能希望为每一行和每一列设置一个单独的监视器(和条件)。您基本上需要考虑所有并发限制 - 如果您不了解您要实现的目标,就很难提供更多指导。

关于调用 signal() 时抛出 java.lang.IllegalMonitorStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26384304/

相关文章:

java - 什么时候使用 "getResourceAsStream"方法?

c++ - 我需要 std::atomic<bool> 还是 POD bool 足够好?

Linux 2.6.31 调度程序和多线程作业

c# - 在多线程环境中创建实例

java - 为什么我们使用 web.xml?

java - 如何更快地阅读 BufferedReader

python - 信号未从线程传递到 GUI

java - spring mvc Controller 中的线程不工作

java - 如何处理 android fragment 中的后退按钮按下

java - 杀死java中的无限循环线程