Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

synchronize on multiple objects

In a previous question -> my question here i received a good solution (which works) to resolve my issue. But i haven't understand how exactly works.

So if i have many threads that can enter concurrently on this synchronized block, and according to the java docs this code is:

synchronized(...){
   //atomic for the operation inside 
}

So, i' m asking:

why this operation is atomic:

for (int j = 0; j < column; j++) {
                    matrix[row][j] += 1;
                }

and not this one:

       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");

my full function is this:

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

Could someone provide me a useful explanation, i'll appreciate a lot.

like image 848
Yokupoku Maioku Avatar asked Jun 21 '26 00:06

Yokupoku Maioku


1 Answers

As it's stated in comment, System.out.println is not thread safe operation.

The problem is the way you lock your critical section.

  synchronized (rows.get(row)) { }

This code means, that you are locking on specific row, not the whole table, so if you have N rows, that means N locks exist at the same time, and there fore N threads can run simultaneously populating System.out in parallel.

Locking on a row gives you a better parallelism: Thread working on row 2, can work at the same time, as Thread working on row 3.

Another option is to have a single lock for the whole table section.

Object lock = new Object();
...
public void someMethod(){
    synchronized(lock){...}
}

In this case there is only one lock, and only one Thread executing it at the same time, so you are effectively calling your System.out synchronously from your code.

Locking on a table, decreases parallelism, since you decrease number of locks, available: Thread working on row 2, would need to wait for Thread working on row 3, to release the lock.

Thread safety, that synchronous guaranties affects only functions, written in the block, not externally called functions, it does not make System.out atomic operation.

like image 187
mavarazy Avatar answered Jun 23 '26 14:06

mavarazy