Java 用于乘法矩阵的同步线程

Java 用于乘法矩阵的同步线程,java,multithreading,synchronization,matrix-multiplication,Java,Multithreading,Synchronization,Matrix Multiplication,我整晚都在研究这个问题,还没有找到解决办法,所以如果有人能帮助我,我将非常感激!我可能错过了一些非常明显的东西。这是一个理解同步的赋值,我们在前面的赋值中使用线程乘以2个矩阵。在上一次分配中,每个线程乘以一行,因此线程数与行数相同 在这个任务中,我们只需要使用5个线程,所有线程都应该从一行/列开始,一旦线程完成,它就应该使用同步选择下一个可用的行/列,所以现在两个线程将完成相同的列 帮助我朝着正确的方向前进,但我肯定是在实施过程中出了问题,因为到目前为止,我只让程序实现了以下两个方面: 5个线程

我整晚都在研究这个问题,还没有找到解决办法,所以如果有人能帮助我,我将非常感激!我可能错过了一些非常明显的东西。这是一个理解同步的赋值,我们在前面的赋值中使用线程乘以2个矩阵。在上一次分配中,每个线程乘以一行,因此线程数与行数相同

在这个任务中,我们只需要使用5个线程,所有线程都应该从一行/列开始,一旦线程完成,它就应该使用同步选择下一个可用的行/列,所以现在两个线程将完成相同的列

帮助我朝着正确的方向前进,但我肯定是在实施过程中出了问题,因为到目前为止,我只让程序实现了以下两个方面:

  • 5个线程只执行一次前5行,每个线程计算一行或多行
  • 我添加了一个循环(现在在我的代码中注释掉了),这样线程将继续执行,但当我这样做时,只有第一个线程执行任何工作
  • 这是我的类,包含main和几个helper方法:

    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Random;
    import java.util.Scanner;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.locks.Lock;
    
    public class MatrixMult {
    
    public static void main(String[] args){
        int[][] matrixA;
        int[][] matrixB;
        int colA = 0;
        int rowA = 0;
        int colB = 0;
        int rowB = 0;
        Scanner userInput = new Scanner( System.in );
        System.out.println("Please enter the dimensions of matrix A");
    
        do{
            System.out.print("column for matrix A: ");
            colA = userInput.nextInt();
            System.out.println();
        } while(!validDimension(colA));
    
        rowB = colA;
    
        do{
            System.out.print("row for matrix A: ");
            rowA = userInput.nextInt();
            System.out.println();
        } while(!validDimension(rowA));
    
        matrixA = new int[rowA][colA];
    
        System.out.println("Please enter the dimensions of matrix B:");
        do{
            System.out.print("column for matrix B: ");
            colB = userInput.nextInt();
            System.out.println();
        } while(!validDimension(colB));
    
        matrixB = new int[rowB][colB];
    
    
        fillMatrix(matrixA);
        fillMatrix(matrixB);
    
        System.out.println("Would you like to print out matrix A and B? (y/n)");
        String userResponse = userInput.next();
        if(userResponse.equalsIgnoreCase("y")){
            System.out.println("Matrix A:");
            printBackMatrix(matrixA);
            System.out.println();
            System.out.println("Matrix B:");
            printBackMatrix(matrixB);
            System.out.println();
        }
    
    
        int[][] matrixProduct3 = multMatrixWithThreadsSync(matrixA, matrixB);
    
        String fileName = "C:/matrix.txt";
        System.out.println("Matrix product is being written to "+fileName);
        try {
            printMatrixToFile(matrixProduct3, fileName);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    private static int[][] multMatrixWithThreadsSync(int[][] matrixA, int[][] matrixB) {
    
        int[][] matrixProduct = new int[matrixA.length][matrixB[0].length];
        int[] matrixProductColumn = new int[matrixA.length];
    
        Runnable task = new MultMatrixByRow(matrixA, matrixB, matrixProduct);
    
        for(int i=0; i<5; i++){
    
            Thread worker = new Thread(task);
            worker.start();
    //          System.out.println(worker.getName());
            try {
                worker.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return matrixProduct;
    }
    
    private static void printMatrixToFile(int[][] matrix, String fileName) throws IOException{
        PrintWriter userOutput = new PrintWriter(new FileWriter(fileName));
        for(int i=0; i<matrix.length; i++){
            for(int j=0; j<matrix[0].length; j++){
                userOutput.print(matrix[i][j]+" ");
            }
            userOutput.println();
        }
        userOutput.close();
    
    }
    
    private static void printBackMatrix(int[][] matrix) {
        for(int i=0; i<matrix.length; i++){
            for(int j=0; j<matrix[0].length; j++){
                System.out.print(matrix[i][j]+" ");
            }
            System.out.println();
        }
    }
    
    private static void fillMatrix(int[][] matrix) {
        Random rand = new Random();
    
        for(int i=0; i<matrix.length; i++){
            for(int j=0; j<matrix[0].length; j++){
                matrix[i][j] = rand.nextInt(100) + 1;
            }
        }
    
    }
    
    public static boolean validDimension(int dim){
        if (dim <= 0 || dim >1000){
            System.err.println("Dimension value entered is not valid");
            return false;
        }
        return true;
    
    }
    }
    
    导入java.io.FileWriter;
    导入java.io.IOException;
    导入java.io.PrintWriter;
    导入java.util.Random;
    导入java.util.Scanner;
    导入java.util.concurrent.Semaphore;
    导入java.util.concurrent.locks.Lock;
    公共类矩阵结果{
    公共静态void main(字符串[]args){
    int[][]矩阵;
    int[][]矩阵b;
    int=0;
    int-rowA=0;
    int colB=0;
    int-rowB=0;
    扫描仪用户输入=新扫描仪(System.in);
    System.out.println(“请输入矩阵A的尺寸”);
    做{
    系统输出打印(“矩阵A列:”;
    colA=userInput.nextInt();
    System.out.println();
    }而(!validDimension(colA));
    rowB=可乐;
    做{
    系统输出打印(“矩阵A的行:”;
    rowA=userInput.nextInt();
    System.out.println();
    }而(!有效尺寸(rowA));
    matrixA=新整数[rowA][colA];
    System.out.println(“请输入矩阵B的尺寸:”);
    做{
    系统输出打印(“矩阵B列:”);
    colB=userInput.nextInt();
    System.out.println();
    }而(!有效尺寸(colB));
    matrixB=新整数[rowB][colB];
    填充矩阵(matrixA);
    填充矩阵(matrixB);
    System.out.println(“是否要打印矩阵A和B?(y/n)”);
    字符串userResponse=userInput.next();
    if(userResponse.equalsIgnoreCase(“y”)){
    System.out.println(“矩阵A:”);
    打印返回矩阵(矩阵);
    System.out.println();
    System.out.println(“矩阵B:”);
    打印返回矩阵(matrixB);
    System.out.println();
    }
    int[][]matrixProduct3=带线程同步的多矩阵(matrixA,matrixB);
    字符串fileName=“C:/matrix.txt”;
    System.out.println(“矩阵产品正在写入”+文件名);
    试一试{
    printMatrixToFile(matrixProduct3,文件名);
    }捕获(IOE异常){
    //TODO自动生成的捕捉块
    e、 printStackTrace();
    }
    }
    私有静态int[]multmatrix with threadsSync(int[]matrixA,int[]matrixB){
    int[]matrixProduct=new int[matrixA.length][matrixB[0.length];
    int[]matrixProductColumn=新int[matrixA.length];
    可运行任务=新的多矩阵xByRow(matrixA、matrixB、matrixProduct);
    对于(int i=0;i
    
  • 您不是在ressource上同步,您需要共享一个锁对象(在静态上下文中或通过构造函数)
  • 当你甚至不让它们同步工作时,我真的无法弄清楚你的程序中应该同步什么…你启动一个线程,直接等待它停止。 我认为您必须首先启动所有线程,然后在另一个循环中调用每个线程上的连接
  • 另外,我不太确定你的线程应该分别解决什么问题,我认为它们都解决了整个产品矩阵。你需要共享一个变量,用于标识你访问的已处理行

    我可以修复您的代码,但我希望您自己完成这项工作,因为理解线程并发性是一项任务

    编辑:同步的解释:
    Synchronized将对象作为锁,只有一个线程可以为其保存监视器。当监视器用于锁时,线程可以处理块,如果没有,他必须等待获取监视器。
    在您的情况下,可以使用
    私有静态最终对象锁=新对象();
    作为锁,您将在上同步

    编辑2:我完全构建了您的代码
    我对你完成所有的工作并不感到骄傲,但没关系,就在这里

    package anything.synchronize_stackoverflow_post;
    
    /**
     * @date 21.11.2012
     * @author Thomas Jahoda
     */
    public class ConcurrentMatrixMultiplyingTask implements Runnable {
    
        private int[][] matrixA;
        private int[][] matrixB;
        private int[][] matrixProduct;
        //
        private final ConcurrencyContext context;
    
        public ConcurrentMatrixMultiplyingTask(ConcurrencyContext context, int[][] A, int[][] B, int[][] C) {
            if (context == null) {
                throw new IllegalArgumentException("context can not be null");
            }
            this.context = context;
            this.matrixA = A;
            this.matrixB = B;
            this.matrixProduct = C;
        }
    
        @Override
        public void run() {
            while (true) {
                int row;
                synchronized (context) {
                    if (context.isFullyProcessed()) {
                        break;
                    }
                    row = context.nextRowNum();
                }
                System.out.println(Thread.currentThread().getName() + " is going to process row " + row);
                // i'm not really sure if this matrix algorithm here is right, idk..
                for (int j = 0; j < matrixB[0].length; j++) {
                    for (int k = 0; k < matrixA[0].length; k++) {
                        matrixProduct[row][j] += matrixA[row][k] * matrixB[k][j];
                    }
                }
            }
        }
    
        public static class ConcurrencyContext {
    
            private final int rowCount;
            private int nextRow = 0;
    
            public ConcurrencyContext(int rowCount) {
                this.rowCount = rowCount;
            }
    
            public synchronized int nextRowNum() {
                if (isFullyProcessed()) {
                    throw new IllegalStateException("Already fully processed");
                }
                return nextRow++;
            }
    
            public synchronized boolean isFullyProcessed() {
                return nextRow == rowCount;
            }
        }
    }
    
    package anything.synchronize\u stackoverflow\u post;
    /**
    *@date 21.11.2012
    *@作者托马斯·贾霍达
    */
    公共类ConcurrentMatrixMultiplyingTask实现Runnable{
    私有int[][]矩阵;
    私有int[][]矩阵b;
    私有int[][]矩阵产品;
    //
    私有最终并发上下文;
    公共ConcurrentMatrixMultiplyingTask(ConcurrentyContext上下文,int[]A,int[]B,int[]C){
    if(上下文==null){
    抛出新的IllegalArgumentException(“上下文不能为null”);
    }
    this.context=上下文;
    这个矩阵=A;
    这个矩阵xb=B;
    this.matrixProduct=C;
    }
    @凌驾
    公开募捐{
    while(true){
    int行;
    已同步(上下文){
    if(context.isFullyProcessed()){
    打破
    }
    row=context.nextRowNum();
    }
    System.out.println(Thread.currentThread().getName()+“将处理行”+行);
    //我不确定这里的矩阵算法是否正确,idk。。
    对于(int j=0;jpackage anything.synchronize_stackoverflow_post;
    
    /**
     * @date 21.11.2012
     * @author Thomas Jahoda
     */
    public class ConcurrentMatrixMultiplyingTask implements Runnable {
    
        private int[][] matrixA;
        private int[][] matrixB;
        private int[][] matrixProduct;
        //
        private final ConcurrencyContext context;
    
        public ConcurrentMatrixMultiplyingTask(ConcurrencyContext context, int[][] A, int[][] B, int[][] C) {
            if (context == null) {
                throw new IllegalArgumentException("context can not be null");
            }
            this.context = context;
            this.matrixA = A;
            this.matrixB = B;
            this.matrixProduct = C;
        }
    
        @Override
        public void run() {
            while (true) {
                int row;
                synchronized (context) {
                    if (context.isFullyProcessed()) {
                        break;
                    }
                    row = context.nextRowNum();
                }
                System.out.println(Thread.currentThread().getName() + " is going to process row " + row);
                // i'm not really sure if this matrix algorithm here is right, idk..
                for (int j = 0; j < matrixB[0].length; j++) {
                    for (int k = 0; k < matrixA[0].length; k++) {
                        matrixProduct[row][j] += matrixA[row][k] * matrixB[k][j];
                    }
                }
            }
        }
    
        public static class ConcurrencyContext {
    
            private final int rowCount;
            private int nextRow = 0;
    
            public ConcurrencyContext(int rowCount) {
                this.rowCount = rowCount;
            }
    
            public synchronized int nextRowNum() {
                if (isFullyProcessed()) {
                    throw new IllegalStateException("Already fully processed");
                }
                return nextRow++;
            }
    
            public synchronized boolean isFullyProcessed() {
                return nextRow == rowCount;
            }
        }
    }
    
    package anything.synchronize_stackoverflow_post;
    
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Random;
    import java.util.Scanner;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    /**
     * @date 21.11.2012
     * @author Thomas Jahoda
     */
    public class MatrixMulti {
    
        public static void main(String[] args) {
            int[][] matrixA;
            int[][] matrixB;
            int colA = 0;
            int rowA = 0;
            int colB = 0;
            int rowB = 0;
            Scanner userInput = new Scanner(System.in);
            System.out.println("Please enter the dimensions of matrix A");
    
            do {
                System.out.print("column for matrix A: ");
                colA = userInput.nextInt();
                System.out.println();
            } while (!validDimension(colA));
    
            rowB = colA;
    
            do {
                System.out.print("row for matrix A: ");
                rowA = userInput.nextInt();
                System.out.println();
            } while (!validDimension(rowA));
    
            matrixA = new int[rowA][colA];
    
            System.out.println("Please enter the dimensions of matrix B:");
            do {
                System.out.print("column for matrix B: ");
                colB = userInput.nextInt();
                System.out.println();
            } while (!validDimension(colB));
    
            matrixB = new int[rowB][colB];
    
    
            fillMatrix(matrixA);
            fillMatrix(matrixB);
    
            System.out.println("Would you like to print out matrix A and B? (y/n)");
            String userResponse = userInput.next();
            if (userResponse.equalsIgnoreCase("y")) {
                System.out.println("Matrix A:");
                printBackMatrix(matrixA);
                System.out.println();
                System.out.println("Matrix B:");
                printBackMatrix(matrixB);
                System.out.println();
            }
    
    
            int[][] matrixProduct3 = multMatrixWithThreadsSync(matrixA, matrixB);
    
            String fileName = "test.txt";
            System.out.println("Matrix product is being written to " + fileName);
            try {
                printMatrixToFile(matrixProduct3, fileName);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        private static int[][] multMatrixWithThreadsSync(int[][] matrixA, int[][] matrixB) {
    
            int[][] matrixProduct = new int[matrixA.length][matrixB[0].length];
            int[] matrixProductColumn = new int[matrixA.length];
            //
            ConcurrentMatrixMultiplyingTask.ConcurrencyContext context = new ConcurrentMatrixMultiplyingTask.ConcurrencyContext(matrixProduct.length);
            //
            Runnable task = new ConcurrentMatrixMultiplyingTask(context, matrixA, matrixB, matrixProduct);
            Thread[] workers = new Thread[5];
            for (int i = 0; i < workers.length; i++) {
                workers[i] = new Thread(task, "Worker-"+i);
            }
            for (int i = 0; i < workers.length; i++) {
                Thread worker = workers[i];
                worker.start();
            }
            for (int i = 0; i < workers.length; i++) {
                Thread worker = workers[i];
                try {
                    worker.join();
                } catch (InterruptedException ex) {
                    Logger.getLogger(MatrixMulti.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            return matrixProduct;
        }
    
        private static void printMatrixToFile(int[][] matrix, String fileName) throws IOException {
            PrintWriter userOutput = new PrintWriter(new FileWriter(fileName));
            for (int i = 0; i < matrix.length; i++) {
                for (int j = 0; j < matrix[0].length; j++) {
                    userOutput.print(matrix[i][j] + " ");
                }
                userOutput.println();
            }
            userOutput.close();
    
        }
    
        private static void printBackMatrix(int[][] matrix) {
            for (int i = 0; i < matrix.length; i++) {
                for (int j = 0; j < matrix[0].length; j++) {
                    System.out.print(matrix[i][j] + " ");
                }
                System.out.println();
            }
        }
    
        private static void fillMatrix(int[][] matrix) {
            Random rand = new Random();
    
            for (int i = 0; i < matrix.length; i++) {
                for (int j = 0; j < matrix[0].length; j++) {
                    matrix[i][j] = rand.nextInt(100) + 1;
                }
            }
    
        }
    
        public static boolean validDimension(int dim) {
            if (dim <= 0 || dim > 1000) {
                System.err.println("Dimension value entered is not valid");
                return false;
            }
            return true;
    
        }
    }
    
    class Cell;  // int x, int y, getters, setters, ...
    // build the structure that contains the work to be shared
    List<Cell> cells = new LinkedList<Cell>();
    for (int i=0;i<a.rows;i++) {
       for (int j=0;j<b.columns;j++) {
           cells.add(new Cell(i,j)); // represent the cells of my result matrix
       }
    }
    
    class DotProduct implements Runnable {
     int[][] a;
     int[][] b;
     int[][] result; 
     List<Cell> cells;
     public DotProduct(int[][] a, int[][] b, int[][]result, List<Cell> cells) {
     ...
     }
     public void run() {
         while(true) {
             Cell cell = null;
             synchronized(cells) { // here, we ensure exclusive access to the shared mutable structure
                 if (cells.isEmpty()) return; // when there're no more cells, we are done.
                 Cell cell = cells.get(0); // get the first cell not calculated yet
                 cells.remove(cell);  // remove it, so nobody else will work on it
             }
             int x = cell.getX();
             int y = cell.getY();
             z = a.row(x) (dot) b.column(y);
             synchronized (result) {
                 result[x][y] = z;
             }
         }
    }