该代码适用于 notifyAll,但不适用于 notify
Posted
技术标签:
【中文标题】该代码适用于 notifyAll,但不适用于 notify【英文标题】:The code works with notifyAll, but doesn't with notify 【发布时间】:2013-03-31 05:10:58 【问题描述】:我正在尝试创建一个带有两个线程的简单“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();
【问题讨论】:
【参考方案1】:从代码中删除 ping.join 即可。 ping.join 使主线程等待 ping 实例,因此您有 2 个线程等待 ping。这就是它仅适用于 notifyAll 的原因。
其实连接是不需要的,Java 会等待 Ping 和 Pong 都终止
如果您使用单独的锁进行同步,则不会出现此类问题。在线程上同步(Ping 是线程)是个坏主意
线程协调是不可靠的,它依赖于线程调度程序。这个
notify();
wait();
可能是个问题。假设您发送 notify() 并且当当前线程移动到 wait() 时,另一个线程醒来完成它的工作并发送 notify() ,如果当前线程尚未到达 wait() 但通知将丢失。你可以很容易地模拟这个场景,看看它是不是真的。
【讨论】:
非常感谢!没想到主线程也在等待资源:)以上是关于该代码适用于 notifyAll,但不适用于 notify的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL 代码适用于 Windows 但不适用于 Mac
查询适用于 phpMyAdmin,但不适用于 Java [重复]
Angular CORS 适用于 GET 但不适用于 DELETE
我的代码适用于输入文件,但不适用于其他文件。 (调试断言错误)