Search code examples
javamultithreadingsynchronizationsleeprunnable

Why Synchronization not working properly with while extending to Thread?


Currently, I'm studying "synchronization", while I was doing an exercise on the synchronization method I couldn't able to get a proper output but when I'm trying the same exercise by implementing Runnable it's working fine. I don't know why it's happening like this. could anyone please help me out here?

By extending Thread

public class ClassRoom extends Thread {
    
    
    synchronized public void run() {
        
        
        try {
            
        System.out.println(Thread.currentThread().getName() + " enters class room");
        
            Thread.sleep(1000);
        
        System.out.println(Thread.currentThread().getName() + " teaching students");
        
            Thread.sleep(1000);
        
        System.out.println(Thread.currentThread().getName() + " exits class room");
        
        
        } catch(InterruptedException ie) {
            ie.getMessage();
        }
    }

}

By implementing Runnable

public class ClassRoom implements Runnable {

rest of the codes are same

Main method (by extending Thread)

public class ClassRoomApp  {

    public static void main(String[] args) throws InterruptedException {
        

        ClassRoom physics_class = new ClassRoom();
        ClassRoom cs_class = new ClassRoom();
        ClassRoom english_class = new ClassRoom();
        
        physics_class.setName("Physics teacher");
        cs_class.setName("CS teacher");
        english_class.setName("English teacher");
        

        physics_class.start();
        cs_class.start();
        english_class.start();
        
    }

}

Main method (by implementing Runnable)

public class ClassRoomApp  {

    public static void main(String[] args) throws InterruptedException {
        
        ClassRoom class_room = new ClassRoom();
    
        Thread t1 = new Thread(class_room);
        Thread t2 = new Thread(class_room);
        Thread t3 = new Thread(class_room);
            
        t1.setName("Physics teacher");
        t2.setName("CS teacher");
        t3.setName("English teacher");
    
        t1.start();
        t2.start();
        t3.start();
        
    }

}

These are the outputs im getting :

While implementing Runnable :

Physics teacher enters class room
Physics teacher teaching students
Physics teacher exits class room
English teacher enters class room
English teacher teaching students
English teacher exits class room
CS teacher enters class room
CS teacher teaching students
CS teacher exits class room

While extending Thread :

Physics teacher enters class room
English teacher enters class room
CS teacher enters class room
English teacher teaching students
Physics teacher teaching students
CS teacher teaching students
English teacher exits class room
CS teacher exits class room
Physics teacher exits class room

I've tried removing the Thread.sleep() from the Thread extended class then it sometimes working sometimes not woring.

These are the outputs :

first try :

CS teacher enters class room
Physics teacher enters class room
Physics teacher teaching students
English teacher enters class room
Physics teacher exits class room
CS teacher teaching students
English teacher teaching students
CS teacher exits class room
English teacher exits class room

second try : (works)

Physics teacher enters class room
Physics teacher teaching students
Physics teacher exits class room
English teacher enters class room
English teacher teaching students
English teacher exits class room
CS teacher enters class room
CS teacher teaching students
CS teacher exits class room


Solution

  • With the Runnable implementation, you are sharing a single instance across all threads. In the former, you are having 3 separate instances.

    To match the behavior of separate threads with a runnable, you have to use separate runnables too:

    public class ClassRoomApp  {
    
        public static void main(String[] args) throws InterruptedException {
            
            Thread t1 = new Thread(new ClassRoom()); // <- distinct instance
            Thread t2 = new Thread(new ClassRoom()); // <- distinct instance
            Thread t3 = new Thread(new ClassRoom()); // <- distinct instance
                
            t1.setName("Physics teacher");
            t2.setName("CS teacher");
            t3.setName("English teacher");
        
            t1.start();
            t2.start();
            t3.start();
            
        }
    
    }