There is no problem when I run the following code with jdk1.8, but it will block when I run it with jdk11

83 Views Asked by At
public class Test {
    public static int num = 0;

    public static void main(String[] args) {
        new Thread(Test::printer, "t0").start();
        new Thread(Test::printer, "t1").start();
        new Thread(Test::printer, "t2").start();
    }

    public static void printer() {
        synchronized (Test.class) {
            while (num < 100) {
                if (Thread.currentThread().getName().contains(String.valueOf(num % 3))) {
                    System.out.println(Thread.currentThread().getName() + ": " + num++);

                }
                Test.class.notifyAll();
                try {
                    Test.class.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            Test.class.notifyAll();
        }
    }
}

There is no problem when I run the following code with jdk1.8.It can output 0 to 99.But when I use jdk11 to run the code,it stop on 2 or 3.I used jstack to check the threads state,the result is following:

"Monitor Ctrl-Break" #21 daemon prio=5 os_prio=0 cpu=15.63ms elapsed=10.26s tid=0x000001ccc56cf800 nid=0x5424 runnable  [0x000000a410efe000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0([email protected]/Native Method)
        at java.net.SocketInputStream.socketRead([email protected]/SocketInputStream.java:115)
        at java.net.SocketInputStream.read([email protected]/SocketInputStream.java:168)
        at java.net.SocketInputStream.read([email protected]/SocketInputStream.java:140)
        at sun.nio.cs.StreamDecoder.readBytes([email protected]/StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead([email protected]/StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read([email protected]/StreamDecoder.java:178)
        - locked <0x00000007181038c8> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read([email protected]/InputStreamReader.java:181)
        at java.io.BufferedReader.fill([email protected]/BufferedReader.java:161)
        at java.io.BufferedReader.readLine([email protected]/BufferedReader.java:326)
        - locked <0x00000007181038c8> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine([email protected]/BufferedReader.java:392)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:56)

"t0" #22 prio=5 os_prio=0 cpu=0.00ms elapsed=10.25s tid=0x000001ccc56d0000 nid=0x6560 in Object.wait()  [0x000000a4110fe000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.lang.Object.wait([email protected]/Native Method)
        - waiting on <0x0000000718113e10> (a java.lang.Class for com.chen.Test)
        at java.lang.Object.wait([email protected]/Object.java:328)
        at com.chen.Test.printer(Test.java:21)
        - waiting to re-lock in wait() <0x0000000718113e10> (a java.lang.Class for com.chen.Test)
        at com.chen.Test$$Lambda$14/0x0000000800066840.run(Unknown Source)
        at java.lang.Thread.run([email protected]/Thread.java:834)

"t1" #23 prio=5 os_prio=0 cpu=3718.75ms elapsed=10.25s tid=0x000001ccc56d1000 nid=0x7b8 in Object.wait()  [0x000000a4111ff000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.lang.Object.wait([email protected]/Native Method)
        - waiting on <no object reference available>
        at java.lang.Object.wait([email protected]/Object.java:328)
        at com.chen.Test.printer(Test.java:21)
        - waiting to re-lock in wait() <0x0000000718113e10> (a java.lang.Class for com.chen.Test)
        at com.chen.Test$$Lambda$15/0x0000000800066c40.run(Unknown Source)
        at java.lang.Thread.run([email protected]/Thread.java:834)

"t2" #24 prio=5 os_prio=0 cpu=4140.63ms elapsed=10.25s tid=0x000001ccc56d2000 nid=0x6620 in Object.wait()  [0x000000a4112ff000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait([email protected]/Native Method)
        - waiting on <no object reference available>
        at java.lang.Object.wait([email protected]/Object.java:328)
        at com.chen.Test.printer(Test.java:21)
        - waiting to re-lock in wait() <0x0000000718113e10> (a java.lang.Class for com.chen.Test)
        at com.chen.Test$$Lambda$16/0x0000000800066040.run(Unknown Source)
        at java.lang.Thread.run([email protected]/Thread.java:834)

t0 and t1 are both BLOCKED,but then none of them get the cpu, So who can tell me why I got this result?

2

There are 2 best solutions below

1
NickH On

When I updated from java 8 to 11. I had to add extra dependencies and exclude some existing once from the pom. Java 11 has many jars that was't in java 8. hope this helps :)

0
steffen On

Summary of what your code does

You create 3 threads and let them run static printer() in parallel. Within a synchronized loop, the current thread increments a number if it is responsible for doing so (%3). Still inside the loop, you let the JVM select one of the other threads to continue while putting the current thread into the wait state.

What happens

notifyAll():

See the notify method for a description of the ways in which a thread can become the owner of a monitor.

notify():

If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.

What happens is that the monitor acquisition toggles between only 2 of the 3 threads, while the third thread, that happens to be responsible for incrementing the current value, does not come to the fore.

Oh, you need to make the variable volatile to ensure all threads read the most recent updated value. I think that this could already have been a valid reason for the observed behavior.