1

我正在尝试创建一个带有两个线程的简单“Ping-Pong”程序(Pong 线程仅在 Ping 线程之后打印他的消息)。

问题是为什么下面的代码一直卡住,但在notifyAll?

这是我的代码:

public class Main {
private static class Ping extends Thread {
    private int rounds;
    Ping(int rounds) { this.rounds = rounds; }
    @Override
    public void run() {
        try {
            synchronized(this) {
                while(rounds > 0) {
                    System.out.println("Ping");
                    notify();
                    wait();
                    --rounds;
                }
                notify();
            }
            System.out.println("Ping done");
        } catch(Exception ignored) { ignored.printStackTrace(); }
    }

    public boolean isDone() { return rounds <= 0; }
}

private static class Pong extends Thread {
    private final Ping ping;
    Pong(Ping ping) { this.ping = ping; }
    @Override
    public void run() {
        try {
            synchronized(ping) {
                while(!ping.isDone()) {
                    System.out.println("Pong");
                    ping.notify();
                    ping.wait();
                }
            }
            System.out.println("Pong done");
        } catch(Exception ignored) { ignored.printStackTrace(); }
    }
}

public static void main(String[] args) throws Exception {
    Ping ping = new Ping(15);
    Pong pong = new Pong(ping);

    ping.start();
    pong.start();

    ping.join();
    pong.join();
}
}
4

1 回答 1

2

从代码中删除 ping.join 它将起作用。ping.join 使主线程等待 ping 实例,因此您有 2 个线程等待 ping。这就是为什么它只适用于 notifyAll。

实际上不需要连接,Java 将等待 Ping 和 Pong 终止

如果您使用单独的锁进行同步,则不会出现此类问题。在线程上同步(Ping 是一个线程)是个坏主意

线程协调是不可靠的,它取决于线程调度程序。这

notify();
wait();

可能是个问题。假设您发送 notify() 并且当当前线程移动到 wait() 时,另一个线程醒来完成它的工作并发送 notify() ,如果当前线程尚未到达 wait() 但通知将丢失。您可以轻松地模拟此场景以查看其真实性。

于 2013-03-31T06:17:22.447 回答