Junior
Junior

Reputation: 113

Unable to synchronize two threads when Thread class is extended but works when implementing Runnable interface

Here the synchronized block is not working:

class NewThreadt extends Thread {
synchronized void dota(){
      for(int i = 5; i > 0; i--)
      {
      System.out.println(i);
  try { 
        Thread.sleep(500); 

    } catch (InterruptedException e) { 
      System.out.println("Child interrupted."); 
    } 
      }

  }

  // This is the entry point for the second thread. 
  public void run() { 
    dota() ;
    System.out.println("Exiting child thread."); 
    System.out.println(Thread.currentThread());    //gives the name of thread 

  } 
} 

class trial { 
  public static void main(String args[]) { 
    NewThreadt t=new NewThreadt();
    NewThreadt q=new NewThreadt();
    t.start();
    q.start();   both are in main


    System.out.println("Main thread exiting."); 
  } 
}

Output:

Main thread exiting.
5
5
4
4
3
3
2
2
1
1

But when I make the following changes the Synchronized Block works:

class NewThreadt implements Runnable  //instead of class NewThreadt extends Thread 

NewThreadt abc=new NewThreadt();  //Changes in main()
Thread t=new Thread(abc);    
Thread q=new Thread(abc);
t.start();
q.start(); 

Output:

Main thread exiting.
5
4
3
2
1    
5
4
3
2
1

Why is this happening? Aren't both of these examples supposed to work the same?

Upvotes: 1

Views: 53

Answers (1)

Nathan Hughes
Nathan Hughes

Reputation: 96444

Synchronization depends on sharing a common lock. The synchronized keyword on an instance method means that for a thread to enter that method it first has to acquire the lock on this.

In your first example there is no shared lock, each of the two threads is locking on itself. Each thread acquires its own lock and nobody blocks, the two threads run concurrently. (The only locking going on here is that when a thread wants to write to the console it has to acquire the console's lock first, so that each println takes place atomically.)

In the second example the same Runnable is passed into each thread, so they both lock on the same object, the Runnable. One thread acquires the lock and executes, the other has to wait for the first thread to release the lock.

If you change the second example to give each thread a separate Runnable:

Thread t=new Thread(new NewThreadt());    
Thread q=new Thread(new NewThreadt());
t.start();
q.start(); 

then you'll see synchronization doesn't work and it behaves like the first example.

Upvotes: 3

Related Questions