synchronized块不会阻止不同的对象

时间:2014-10-21 15:31:55

标签: java multithreading

我插入了一个hashMap(对于每一行):

rows.put(currentRow, new Object());
....

并且在某些线程之后将调用此函数:

   @Override
    public void run() {
        while (true) {
            increaseRow(new Random().nextInt(10));
            try {
                sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
      }

public  void increaseRow(Integer row) {
        synchronized (rows.get(row)) {
            for (int j = 0; j < column; j++) {
                matrix[row][j] += 1;
            }
            System.out.println("begin print");
            for (int i = 0; i < this.row; i++) {
                System.out.println();
                for (int j = 0; j < column; j++)
                    System.out.print(matrix[i][j]);
            }
            System.out.println();
            System.out.println("end print");
        }
   }

如果我启动1个线程,它可以正常工作,但是有更多线程存在一些问题,例如:

begin print
00000
begin print
00
0000000000000000
00
000000000000000000000
00000000000
00000000000000
00000000000
00
000000000000
111111111111
000000000000
111000000000000
000000000000
111111111111
000000000000
111111111111
000000000000
0000000100000
end print

地图只有10个键值,i&#39;我同步对象值,所以我不明白错误。

提前感谢。

2 个答案:

答案 0 :(得分:1)

强制它仅打印&#39;开始打印&#39;然后&#39;结束打印&#39;对于每行更新(不交错),您需要在&#39;行上进行同步。宾语。

虽然一次只有一个线程可以写入rows.get(0)对象,但仍然可以对rows.get(0)和rows.get(1)以及rows.get(2)对象进行锁定同时。这意味着您的输出可以包含&#39;开始打印&#39;连续多次,然后是多次打印&#39;线。

根据您在此处尝试实现的内容 - 我只会输出您正在更新的行,因为您知道可以同时执行两行 - 仅同步您想要的行。

public  void increaseRow(Integer row) {
    synchronized (rows.get(row)) {
        for (int j = 0; j < column; j++) {
            matrix[row][j] += 1;
        }
        System.out.println(String.format("begin update row %s", row));
        for (int i = 0; i < this.row; i++) {
            System.out.println();
            for (int j = 0; j < column; j++)
                System.out.print(String.format("row %s value %s",row,matrix[i][j]));
        }
        System.out.println();
        System.out.println("String.format("end update row %s", row)");
    }

}

或者如果您只是希望每个线程告诉您更新了哪一行:

    public  void increaseRow(Integer row) {
        synchronized (rows.get(row)) {
            for (int j = 0; j < column; j++) {
                matrix[row][j] += 1;
                System.out.print(String.format("row %s value %s",row,matrix[row][j]));
            }
        }
   }

答案 1 :(得分:0)

由于您在同一行上同步访问权限,因此打印会被加扰。因此,两个不同行的更新可能会交错。除了打印看起来乱码之外,这可能还不错。

要同步打印(有多行可以并行更新,但只有一个屏幕),请执行以下操作:

public  void increaseRow(Integer row) {
  synchronized (rows.get(row)) {
    for (int j = 0; j < column; j++) {
      matrix[row][j] += 1;
    }

    // Printing here makes sense for debugging only

    synchronized (rows) (
      System.out.println("begin print");
      for (int i = 0; i < this.row; i++) {
        System.out.println();
        for (int j = 0; j < column; j++)
          System.out.print(matrix[i][j]);
      }
      System.out.println();
      System.out.println("end print");
    }
  }
}

顺便说一下:为什么要使用哈希映射来代替行锁而不只是数组呢?