简体   繁体   English

Java中的多线程矩阵乘法

[英]Multithreading matrix multiplication in Java

i'm trying to build a program for multiplying two matrices (A[a,b], B[c,d]) using a*d threads (that will be used to print the sum of one index in the finished matrix), for this purpose, i'm using a 'monitor' class that will be used as a controller to synchrosize between the threads, 'multiplier' class to represent the single thread and a main program class. 我正在尝试使用* d个线程(用于打印完成矩阵中一个索引的总和)构建一个用于乘以两个矩阵(A [a,b],B [c,d])的程序,为此,我使用了一个'monitor'类,它将用作控制器来实现线程之间的同步,'multiplier'类用来表示单个线程和一个主程序类。 My idea is that the threads will have their calculations, and when thread(0,0) will print his sum, he will signal the next in line. 我的想法是线程将进行计算,当线程(0,0)将打印他的总和时,他将发出下一个信号。 For some reason after printing the first index - all the threads stay in waiting mode and won't test my condition. 由于某种原因,在打印第一个索引后 - 所有线程都处于等待模式并且不会测试我的状况。 Could you look at my code and tell me where is my mistake? 你能看看我的代码并告诉我我的错误在哪里吗?

Monitor class: 监控类:

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

Multiplier: 乘数:

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

Main class: 主要课程:

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

The finished() method is riddled with problems: finished()方法充满了问题:

  • The first problem is the synchronized keyword. 第一个问题是synchronized关键字。 It must be removed. 它必须被删除。 With this keyword, if the first entering thread has a non-zero index, the program will deadlock - the thread will forever be parked waiting for the condition to signal, which will never come, because no other thread can enter the finished() method. 使用此关键字,如果第一个进入的线程具有非零索引,程序将死锁 - 线程将永远停在等待条件发出信号,这将永远不会到来,因为没有其他线程可以进入finished()方法。

  • The second fault lies with the else block: 第二个错误在于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) {};
}

It never invokes cond.signalAll() , so after the thread with index=0 gets through, others will stay parked forever. 它永远不会调用cond.signalAll() ,所以在index=0的线程通过后,其他线程将永远停留。

  • The third problem is that in if(index != x) {.. block, cond.signalAll() and lock.unlock() come in wrong order: 第三个问题是if(index != x) {.. block, cond.signalAll()lock.unlock()顺序错误:
lock.unlock();
cond.signalAll();

Condition 's signalAll() method documentation states: ConditionsignalAll()方法文档说明:

An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called. 当调用此方法时,实现可能(并且通常确实)要求当前线程保持与此Condition关联的锁。 Implementations must document this precondition and any actions taken if the lock is not held. 实现必须记录此前提条件以及未保持锁定时所采取的任何操作。 Typically, an exception such as IllegalMonitorStateException will be thrown. 通常,将抛出异常,例如IllegalMonitorStateException

These two lines of code must be switched in order, or an IllegalMonitorStateException will be thrown. 必须按顺序切换这两行代码,否则将抛出IllegalMonitorStateException

A working version of the method can look something like this: 该方法的工作版本可能如下所示:

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

Funny enough, the code provided by OP actually works even with all these faults, but only due to this block of code in the MatrixMultiTest class: 有趣的是,OP提供的代码实际上甚至可以解决所有这些错误,但仅仅是由于MatrixMultiTest类中的MatrixMultiTest代码:

try {
    myThr.join();
} catch (InterruptedException e) {
//  TODO Auto-generated catch block
    e.printStackTrace();
}

Every thread is created and then started and joined sequentially, thus only one thread ever tries to acquire the implicit lock on the synchronized finished() method at any moment in time, and i*5+j index value ensures that the threads acquire this implicit lock in order of their index : 0, 1, 2 etc. It means that inside the method, index is always equal to x , and every thread goes through else block in finished() , allowing the program to complete execution. 每个线程都被创建,然后按顺序启动和连接,因此只有一个线程在任何时刻都尝试获取synchronized synchronized finished()方法的隐式锁,并且i*5+j索引值确保线程获取此隐式按index顺序锁定:0,1,2等。这意味着在方法内部, index始终等于x ,并且每个线程都通过finished() else块,允许程序完成执行。 cond.await() is actually never invoked. cond.await()实际上从未被调用过。

If the join block is removed, then some values might get printed, but the program will eventually deadlock. 如果删除了join块,则可能会打印某些值,但程序最终会死锁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM