Vijay
Vijay

Reputation: 384

Java multithreading synchronized method with two threads

I have a very simple code but unable to understand.

    public class Test extends Thread {
    
        public synchronized void testPrint() {
            System.out.println("I am sleeping..."
                    + Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
                System.out.println("I am done sleeping..."
                        + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public void run() {
            Test t = new Test();
            t.testPrint();
    
            System.out.println("I am out..." + Thread.currentThread().getName());
        }
    
        public static void main(String[] args) {
            Test t1 = new Test();
            Test t2 = new Test();
    
            t1.start();
            t2.start();
    
        }
    }

Here is my questions

When two threads executing Test t = new Test(), does this create two different objects with same name? What happens at this line with multiple threads?

I am getting below result,

I am sleeping...Thread-0

I am sleeping...Thread-1

I am done sleeping...Thread-0

I am out...Thread-0

I am done sleeping...Thread-1

I am out...Thread-1


From the output, It definitely means that there are two objects created, that is why both the threads could enter in the sync method. hope my understanding is correct ? How system maintains these two objects?

Upvotes: 0

Views: 7985

Answers (4)

Ortwin Angermeier
Ortwin Angermeier

Reputation: 6203

With your current approach, you ensure that for each instance of Test the method testPrint() can not run concurrently. It all depends on what you want to do. I assume that you want to protect the testPrint() method from running in multiple threads concurrently, with multiple instances of Test.

Currently you use the synchronized keyword directly on the method. This results in using the object itself (an instance of Test) being used for synchronization.

You should synchronize on another object that is shared between the instances of Test(you could for example make the lock object static).

Also note, that it is general a better idea to implement only the Runnable interface and then pass the implementation to the thread. Plus, you don't have to create a new instance of Test every time you run (i don't see the purpose of that), i commented that out.

public class Test extends Thread {
  // could also use a static monitor instead.
  // private static final Object monitor = new Object();
  private final Object monitor;

  public Test(final Object monitor) {
    this.monitor = monitor;
  }

  public void testPrint() {
    synchronized (monitor) {
      System.out.println("I am sleeping..." + Thread.currentThread().getName());
      try {
        Thread.sleep(3000);
        System.out.println("I am done sleeping..." + Thread.currentThread().getName());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

  public void run() {
    //Test t = new Test(monitor);
    //t.testPrint();
    testPrint();
    System.out.println("I am out..." + Thread.currentThread().getName());
  }

  public static void main(String[] args) {
    // synchronization will happen on this object.
    final Object monitor = new Object();

    Test t1 = new Test(monitor);
    Test t2 = new Test(monitor);

    t1.start();
    t2.start();

  }
}

Upvotes: 2

Trying
Trying

Reputation: 14278

Test t = new Test()

This will create a object in the heap and the reference will be placed in the stack.

Here in your example you dont need the synchronized method at all because you are not sharing the instance among different thread.

Upvotes: 0

Aniket Thakur
Aniket Thakur

Reputation: 69025

You are creating two different object which will have two different monitors on which lock will be acquired. As both thread work on different objects synchronization does not come into picture.

You can try

public class Test extends Thread {

Object obj;

public Test(Object obj){
    this.obj = obj;
}

public synchronized void testPrint() {
    System.out.println("I am sleeping..."
            + Thread.currentThread().getName());
    try {
        Thread.sleep(3000);
        System.out.println("I am done sleeping..."
                + Thread.currentThread().getName());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public void run() {
    ((Test)obj).testPrint();
    System.out.println("I am out..." + Thread.currentThread().getName());
}

public static void main(String[] args) {

    Object obj = new Test(null);

    Test t1 = new Test(obj);
    Test t2 = new Test(obj);

    t1.start();
    t2.start();

}
}

and the output is

I am sleeping...Thread-1
I am done sleeping...Thread-1
I am out...Thread-1
I am sleeping...Thread-2
I am done sleeping...Thread-2
I am out...Thread-2

as expected.

Upvotes: 2

Alexander Kudrevatykh
Alexander Kudrevatykh

Reputation: 870

When you run Test t = new Test() jvm create new object on heap and put variable t with link to that object on stack of current thread.
When you run that code in two or more different threads each of them have own stack, so each of them create his own variable t and object Test

Upvotes: 1

Related Questions