0

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?

user2336315
  • 15,697
  • 10
  • 46
  • 64
  • FYI, this kind of exercise might teach you something about how threads can be synchronized, but it is a truly horrible example if you want to know when or why they should be synchronized. Forcing two threads to operate in lock-step like this is much less efficient than letting one thread do all the work. Multithreading works best when threads can work independently of one another for relatively long spans of time, and only occasionally meet up to compare/combine results. – Solomon Slow Apr 27 '15 at 13:25

1 Answers1

2

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.

Boris the Spider
  • 59,842
  • 6
  • 106
  • 166
  • Makes sense. 2 questions here: How did you make this thread dump? How to make the thread A to exit? I can add `if(i < 50) {lock.wait();}` in A but it seems an ugly hack or? – user2336315 Apr 26 '15 at 21:34
  • 1) I asked my IDE to do it, but you could use [JVisualVM](https://visualvm.java.net/threads.html) which comes bundled with the JDK. 2) easiest way? Retest `i` before calling `wait`. – Boris the Spider Apr 26 '15 at 21:36
  • Ok I just wondered if there was a more standard idiom. Thanks anyway :) – user2336315 Apr 26 '15 at 21:37