[英]Multithreading matrix multiplication in Java
我正在尝试使用* d个线程(用于打印完成矩阵中一个索引的总和)构建一个用于乘以两个矩阵(A [a,b],B [c,d])的程序,为此,我使用了一个'monitor'类,它将用作控制器来实现线程之间的同步,'multiplier'类用来表示单个线程和一个主程序类。 我的想法是线程将进行计算,当线程(0,0)将打印他的总和时,他将发出下一个信号。 由于某种原因,在打印第一个索引后 - 所有线程都处于等待模式并且不会测试我的状况。 你能看看我的代码并告诉我我的错误在哪里吗?
监控类:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
final class Monitor {
private Lock lock;
int index;
Condition cond;
public Monitor () {
lock = new ReentrantLock();
cond = lock.newCondition();
this.index = 0;
}
public synchronized void finished(int x, double sum) throws InterruptedException {
lock.lock();
if(index != x) {
while(index != x) cond.await();
System.out.printf("%9.2f ",sum);
index++;
lock.unlock();
cond.signalAll();
}
else {
System.out.printf("%9.2f ",sum);
index++;
try { lock.unlock(); }
catch (java.lang.IllegalMonitorStateException e) {};
try { lock.unlock(); }
catch (java.lang.IllegalMonitorStateException e) {};
}
if(index % 5 == 0) System.out.println();
}
}
乘数:
public class Multiplier extends Thread {
private int index;
private double [] vectorOne;
private double [] vectorTwo;
private Monitor monitor;
private double sum;
//constructor
public Multiplier(int index, Monitor monitor,double [] vectorOne,double [] vectorTwo) {
this.index = index;
this.monitor = monitor;
this.vectorOne = vectorOne;
this.vectorTwo = vectorTwo;
}
public void VecMulti() {
sum = 0;
for (int i = 0 ; i < vectorOne.length ; i++)
sum += vectorOne[i] * vectorTwo[i];
}
public double getSum() {
return sum;
}
public void run() {
VecMulti();
try {
monitor.finished(index, sum);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
主要课程:
public class MatrixMultiTest {
public static void main(String[] args) {
Monitor monitor = new Monitor(3*5);
Matrix A = Matrix.random(3,4);
Matrix B = Matrix.random(4,5);
System.out.println("Matrix No1");
A.show();
System.out.println();
System.out.println("Matrix No2");
B.show();
System.out.println();
System.out.println("Multi Matrix");
for (int i = 0; i < 3; i++)
for (int j = 0; j < 5; j++) {
Multiplier myThr = new Multiplier(i*5+j,
monitor,A.getRow(i),B.getCol(j));
myThr.start();
try {
myThr.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
finished()
方法充满了问题:
第一个问题是synchronized
关键字。 它必须被删除。 使用此关键字,如果第一个进入的线程具有非零索引,程序将死锁 - 线程将永远停在等待条件发出信号,这将永远不会到来,因为没有其他线程可以进入finished()
方法。
第二个错误在于else
块:
else {
System.out.printf("%9.2f ",sum);
index++;
try { lock.unlock(); }
catch (java.lang.IllegalMonitorStateException e) {};
try { lock.unlock(); }
catch (java.lang.IllegalMonitorStateException e) {};
}
它永远不会调用cond.signalAll()
,所以在index=0
的线程通过后,其他线程将永远停留。
if(index != x) {..
block, cond.signalAll()
和lock.unlock()
顺序错误: lock.unlock();
cond.signalAll();
Condition
的signalAll()
方法文档说明:
当调用此方法时,实现可能(并且通常确实)要求当前线程保持与此Condition关联的锁。 实现必须记录此前提条件以及未保持锁定时所采取的任何操作。 通常,将抛出异常,例如
IllegalMonitorStateException
。
必须按顺序切换这两行代码,否则将抛出IllegalMonitorStateException
。
该方法的工作版本可能如下所示:
public void finished(int x, double sum) throws InterruptedException {
try {
lock.lock();
while (index != x) {
cond.await();
}
System.out.printf("%9.2f ", sum);
index++;
cond.signalAll();
} finally {
lock.unlock();
}
if (index % 5 == 0) System.out.println();
}
有趣的是,OP提供的代码实际上甚至可以解决所有这些错误,但仅仅是由于MatrixMultiTest
类中的MatrixMultiTest
代码:
try {
myThr.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
每个线程都被创建,然后按顺序启动和连接,因此只有一个线程在任何时刻都尝试获取synchronized synchronized finished()
方法的隐式锁,并且i*5+j
索引值确保线程获取此隐式按index
顺序锁定:0,1,2等。这意味着在方法内部, index
始终等于x
,并且每个线程都通过finished()
else
块,允许程序完成执行。 cond.await()
实际上从未被调用过。
如果删除了join
块,则可能会打印某些值,但程序最终会死锁。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.