Ravi_Kumar
Ravi_Kumar

Reputation: 29

Wait and Notify Deadlock situation in Java

  1. Thread t1 is going into Deadlock after wait() is hit. even though there is notify() in t2. Code is getting into deadlock. Not getting Print statement - "After wait is released ::::"

  2. I can see both threads competing to acquire the monitor in counterAdd(). Therefore, I assumed notify will work.

    package com.java.thread.practice;
    
      public class WaitAndNotify4 {
    
            int counter = 0;
    
            /*
               CounterAdd() is to be accessed by both t1 and t2.
               If not synchronized not giving consistent output. 
            */ 
            synchronized int counterAdd(){
                return counter++;
            }
    
            public static void main(String[] args) throws InterruptedException{
    
                // Creating method to call the threads.
                WaitAndNotify4 andNotify4 = new WaitAndNotify4();
                andNotify4.testRaceCondition();
    
            }
    
            private  void testRaceCondition() throws InterruptedException {
    
                // Thread t1 created and launched.
    
                Thread t1 = new Thread(new Runnable(){
                    @Override
                    public void run() {
    
                        for(int i=0; i<5; i++){
                            synchronized(this){
                            if(i== 1){
                                System.out.println("Calling wait after count 1");
                                try {
                                 // Assuming that this wait will be resumed by notify in t2.
    
                                    wait();
                                    System.out.println("After wait is released :::: ");
                                } catch (InterruptedException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
    
                            }
                            }
                            counterAdd();
                        }
                    }
                });
    
    
                Thread t2 = new Thread(new Runnable(){
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
    
                        for(int i=0; i<5; i++){
                            if(i==2){
    
                                synchronized(this){
                                    System.out.println("Before releasing the counter :::::");
                                    notify();
                                    System.out.println("After releasing the counter :::::");
                                }
    
                            }
                            counterAdd();
                        }
    
                    }
                });
    
    
    
                t1.start();
                t2.start();
    
                t1.join();
                t2.join();
    
                System.out.println(" Sum value is found as ::::: "+counter);
    
            }
        }
    

Upvotes: 1

Views: 287

Answers (1)

Divers
Divers

Reputation: 9569

You are synchronizing on different objects. In first case on object t1, in second on t2, in method counterAdd on andNotify4. In order to place lock on andNotify4 all the time you need to do something like that.

public class Main {
    private int counter = 0;

    synchronized int counterAdd() {
        return counter++;
    }

    public static void main(String[] args) throws InterruptedException {
        Main andNotify4 = new Main();
        andNotify4.testRaceCondition();
    }

    private void testRaceCondition() throws InterruptedException {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    synchronized (Main.this) {
                        if (i == 1) {
                            System.out.println("Calling wait after count 1");
                            try {
                                Main.this.wait();
                                System.out.println("After wait is released :::: ");
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    counterAdd();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    if (i == 2) {
                        synchronized (Main.this) {
                            System.out.println("Before releasing the counter :::::");
                            Main.this.notify();
                            System.out.println("After releasing the counter :::::");
                        }
                    }
                    counterAdd();
                }
            }
        });

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

        t1.join();
        t2.join();

        System.out.println(" Sum value is found as ::::: " + counter);
    }
}

Upvotes: 1

Related Questions