我正在从事多线程计划。线程在矩阵(workerThread)中工作,我有一个线程(显示)打印矩阵状态。我在行监视器的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
答案 0 :(得分:6)
是的,问题在于increaseRow
您在没有先锁定monitor.signal()
的情况下调用lock
。来自Condition.signal()
的文档:
当调用此方法时,实现可能(并且通常确实)要求当前线程保持与此Condition关联的锁。实现必须记录此前提条件以及未保持锁定时所采取的任何操作。通常,会抛出
IllegalMonitorStateException
之类的异常。
您的increaseRow
和increaseColumn
方法都应具有
lock.lock();
try {
// code including monitor.signal() here
} finally {
lock.unlock();
}
就像您的sumRow
,sumColumn
和printMatrix
方法一样。或者,您可能希望为每行和每列分别设置一个监视器(和条件)。您基本上需要考虑所有的并发约束 - 如果不了解您正在尝试实现的目标,就很难提供更多指导。
答案 1 :(得分:4)
在方法increaseRow(int)
和increaseColumn(int)
中,您需要锁定lock
,否则您无法调用monitor.signal()
lock.lock();
try {
....
monitor.signal();
} finally {
lock.unlock();
}
来自signal
的文档当调用此方法时,实现可能(并且通常确实)要求当前线程保持与此Condition关联的锁。
然后是ReentrantLock:
如果在调用任何条件等待或信令方法时未保持此锁定,则抛出IllegalMonitorStateException。