当我用 jdk1.8 运行以下代码时没有问题,但是当我用 jdk11 运行它时它会阻塞

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

提问人:Mr.Chen 提问时间:3/1/2023 更新时间:4/28/2023 访问量:71

问:

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();
        }
    }
}

当我用 jdk1.8.It 可以输出 0 到 99 运行以下代码时没有问题,但是当我使用 jdk11 运行代码时,它会在 2 或 3 停止,我用来检查线程状态,结果如下:jstack

"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 和 t1 都被阻止了,但是它们都没有得到 cpu,那么谁能告诉我为什么我得到了这个结果?

Java 同步 通知

评论


答:

-2赞 NickH 3/1/2023 #1

当我从 java 8 更新到 11 时。我不得不添加额外的依赖项并从 pom 中排除一些现有的依赖项。Java 11 有许多 jar 在 java 8 中没有。希望这对:)有所帮助

评论

0赞 Community 3/7/2023
您的答案可以通过其他支持信息进行改进。请编辑以添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以在帮助中心找到有关如何写出好答案的更多信息。
0赞 steffen 3/7/2023 #2

代码功能摘要

您创建 3 个线程并让它们并行运行。在循环中,如果当前线程负责这样做,则它会递增一个数字 ()。仍然在循环中,您让 JVM 选择其他线程之一以继续,同时将当前线程置于等待状态。static printer()synchronized%3

会发生什么

notifyAll():

有关线程可以成为监视器所有者的方式的说明,请参阅 notify 方法。

notify():

如果有任何线程在此对象上等待,则选择其中一个线程进行唤醒。选择是任意的,由实施自行决定。

发生的情况是,监视器采集仅在 3 个线程中的 2 个线程之间切换,而恰好负责递增当前值的第三个线程不会脱颖而出。

哦,您需要创建变量以确保所有线程都读取最新的更新值。我认为这可能已经是观察到的行为的正当理由。volatile