1

I am completely new to multi threading. Need assistance on the below scenario

Scenario:- I want two threads to execute, such that they have to print the word "PingPong" alternatively. This has to happen three 3 times for both threads.

For example:-

  1. Thread 1 has to print "Ping" and it has to go to wait stage.
  2. Thread 2 has to print "Ping" and it has to go to wait stage as well as notify the other thread.
  3. Thread 1 has to print "Pong" and it has to go to wait stage as well as notify the other thread.
  4. Thread 2 has to print "Pong" and it has to go to wait stage as well as notify the other thread.

The same way both the threads has to print the word 3 times in total.

Coding below:-

package com.test.files;

public class MultiThreadingTest2 implements Runnable {
    String lastExecutedThread = "";
    Object lockObj = new Object();
    private void print(String wordToPrint) throws InterruptedException {
        synchronized(lockObj) {
            if(lastExecutedThread.equals(Thread.currentThread().getName())) {
                System.out.println(Thread.currentThread().getName()+" entered wait stage");
                lockObj.wait();
            } else {
                lastExecutedThread = Thread.currentThread().getName();
                System.out.println(Thread.currentThread().getName()+" printed "+wordToPrint);
                lockObj.notifyAll();
            }
        }
    }
    
    public MultiThreadingTest2(Object lock) {
        this.lockObj = lock;
    }
    
    @Override
    public void run() {
        String[] wordArr = {"Ping", "Pong"};
        
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < wordArr.length; j++) {
                try {
                    print(wordArr[j]);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        
        Thread t1 = new Thread(new MultiThreadingTest2(lock), "Thread 1");
        Thread t2 = new Thread(new MultiThreadingTest2(lock), "Thread 2");
    
        t1.start();
        t2.start();
    }
}

But I could see the above code has resulted in deadlock. Output as follow:-

Thread 1 printed Ping
Thread 1 entered wait stage
Thread 2 printed Ping
Thread 2 entered wait stage
Thread 1 entered wait stage

I am not sure why this has resulted in deadlock. Reason because, the variable "lastExecutedThread " is created at class level. So it should be stored in heap. If its a local variable, then we can say that it could be in thread stack, so the other thread may not what value it possess and because of which the thread executing the print function will have the "lastExecutedThread" to its name and it will lead to deadlock.

Could you please help on this.

user3153356
  • 25
  • 1
  • 4

1 Answers1

1

You have to make lastExecutedThread static, otherwise each Thread sees its own instance of it.

Note that if inside the print method lockObj.wait() is called, the wordToPrint passed to this method is never printed. You can slightly adapt your code to avoid this: if your print method returns true if printing was successful, and false otherwise. Then inside your nested for-loop, put your call of print inside a while-loop: while (!print(wordArr[j]));

user7291698
  • 1,972
  • 2
  • 15
  • 30
  • Thank you. I tried by the way which you mentioned. I could see its working fine as I expected. But still I am not clear on one thing. Normally, the variables which we create at class level will be stored in heap, right? So here, the variable "lastExecutedThread" should be stored in heap and it should be shared by the two threads in their stack(By reference). In this case, the object reference will be shared, right? In this case, why do you expect the variable to be declared as static. Could you please help to clarify this. – user3153356 Jul 22 '22 at 16:51
  • 1
    Yes, variables at class level are normally stored in heap. See e.g. https://stackoverflow.com/q/8387989, https://stackoverflow.com/q/3849634, https://stackoverflow.com/q/23550385. However, I do not think that this is relevant for your question. The relevant thing is that an instance variable (without static-modifier) is associated with its instance, while a class variable (with static modifier) is shared by all instances of the class. See https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.1 – user7291698 Jul 22 '22 at 19:36