[英]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.