Java Thread inter process communication working in boolean variable condition but not in int?

StackOverflow https://stackoverflow.com/questions/22609634

  •  20-06-2023
  •  | 
  •  

Question

I have code to communicating 2 threads in JRE6. When i run following program my expected output is come like,
A: Hi
B: hi
A: How r u?
B: im fine wat about u?
A: I'm fine
B: Me too

class Chat {

    boolean flag = false;

    public synchronized void getTalk1(String msg) throws InterruptedException {
        if (flag) {
            wait();
        }
        System.out.println(msg);
        flag = true;
        notify();
    }

    public synchronized void getTalk2(String msg) throws InterruptedException {
        if (!flag) {
            wait();
        }
        System.out.println(msg);
        flag = false;
        notify();
    }
}

class Thread1 extends Thread {
    Chat chat;

    public Thread1(Chat chat) {
        this.chat = chat;
    }

    String[] talk = { "Hi", "How r u?", "I'm fine" };

    @Override
    public void run() {
        for (int i = 0; i < talk.length; i++) {
            try {
                chat.getTalk1("A: " + talk[i]);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Thread2 extends Thread {
    Chat chat;

    public Thread2(Chat chat) {
        this.chat = chat;
    }

    String[] talk = { "hi", "im fine wat about u?", "Me too" };

    @Override
    public void run() {
        for (int i = 0; i < talk.length; i++) {
            try {
                chat.getTalk2("B: " + talk[i]);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Conversation {
    public static void main(String[] args) {
        Chat chat = new Chat();
        new Thread1(chat).start();
        new Thread2(chat).start();
    }
}

But when i change Chat class flag variable boolean to int type

class Chat {

    volatile int flag = 2;    
    public synchronized void getTalk1(String msg) throws InterruptedException {
        if (flag == 1) {
            wait();
        }
        System.out.println(msg);
        flag = 2;
        notify();
    }

    public synchronized void getTalk2(String msg) throws InterruptedException {
        if (flag == 2) {
            wait();
        }
        System.out.println(msg);
        flag = 1;
        notify();
    }
}

The output is varied and executing not stop like
A: Hi
A: How r u?
A: I'm fine
...still running

What is the reason?

Was it helpful?

Solution

Compare

    if (flag) {
        wait();
    }
    System.out.println(msg);
    flag = true;
    notify();

with

    if (flag == 1) {
        wait();
    }
    System.out.println(msg);
    flag = 2;
    notify();

In the first case, you wait if flag == true and then set flag = true. In the second case, you wait if flag == 1 and then set flag = 2. The logic is inverted.

OTHER TIPS

Just mixed values, in your case flag is always 2.

class Chat {

    int flag = 2;

    public synchronized void getTalk1(String msg) throws InterruptedException {
        if (flag == 2) {
            wait();
        }
        System.out.println(msg);
        flag = 2;
        notify();
    }

    public synchronized void getTalk2(String msg) throws InterruptedException {
        if (flag == 1) {
            wait();
        }
        System.out.println(msg);
        flag = 1;
        notify();
    }
}

Your logic is incorrect when you use int instead of boolean. To make it less confusing use int flag = 0 for false and flag = 1 for true. In multi-threading it is a good practice to write conditions for wait() and notify() in a while loop instead of a if block just to make sure the value of the variable/flag is still the same after the thread wakes up.

e.g. -

class Chat {

    boolean flag = false;

    public synchronized void getTalk1(String msg) throws InterruptedException {
        while (flag) {
            wait();
        }
        System.out.println(msg);
        flag = true;
        notify();
    }

    public synchronized void getTalk2(String msg) throws InterruptedException {
        while (!flag) {
            wait();
        }
        System.out.println(msg);
        flag = false;
        notify();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top