Search code examples
javamultithreadingthread-synchronization

How to stop my program with interleaved thread


Re-learning multithreading there :) I'm trying to use two threads to print them alternatively even and odd numbers until 50.

public class Threading {

    private static final Object lock = new Object();
    private static int i = 0;

    public static void main(String[] args) {
        new Thread(() -> {
            while(i <= 50) {
                synchronized (lock) {
                    System.out.println("A :" + i++);
                    try {
                        lock.notify();
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        new Thread(() -> {
            while(i < 50) {
                synchronized (lock) {
                    System.out.println("B :" + i++);
                    try {
                        lock.notify();
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

This works well and output:

A :0
B :1
...
A :48
B :49
A :50

However the program does not stop after and I don't know why.

My understanding is that when A print 50, it releases the locks for B then the condition is not true for B it releases the lock then it shouldn't be true for A and hence the two threads finish their jobs.

So there might be something wrong in my reasoning :) Could someone explain it to me?


Solution

  • Lets take a thread dump:

    "Thread-0@617" prio=5 tid=0xe nid=NA waiting
      java.lang.Thread.State: WAITING
          at java.lang.Object.wait(Object.java:-1)
          at java.lang.Object.wait(Object.java:502)
          at com.boris.testbench.App.lambda$main$0(App.java:22)
          at com.boris.testbench.App$$Lambda$1.1330278544.run(Unknown Source:-1)
          at java.lang.Thread.run(Thread.java:745)
    

    Line 22 in my code is lock.wait() for the top thread (A), the sequence of events:

    • A prints "A:50"
    • A notifies all
    • A waits on lock
    • B wakes and exits

    So you are left with A locked and nothing to wake it.