更新 事实证明我的Synchronized语句没有任何问题。我之前在代码中犯了一个错误,它在那里阻塞了。我为浪费的时间道歉并感谢您的帮助。
PS。 @ sh0rug0ru建议的CountDownLatch更适合我的需要,正是我所需要的。
PREVIOUS:
这是代码的相关部分:
static final Object readyLock = new Object();
readyLock对象在另一个类中初始化为静态最终变量:
input[type="checkbox"]:checked ~ .nav ul{
display: block;
}
Synchronized语句第一次工作,就像在第一个同步的语句块中一样。但是while循环中的synchronized块并不起作用。它在两个地方都是完全相同的代码。
此类是从服务器运行两次的线程。它适用于双人游戏。其余代码为here。
我试图弄清楚为什么第二个同步语句不起作用。我认为它只是出于某种原因阻止了它。
注意所有System.out.println("");这些行用于调试。
答案 0 :(得分:3)
使用notify()
时,会出现状态更改。
当你wait()
时,你应检查状态变化。
否则你冒险;
notify
就会丢失。wait
可以虚假地醒来。这些方法的文档中对此进行了介绍。
答案 1 :(得分:0)
请勿使用notify
,请使用notifyAll
。 notify
会选择一个随机等待的帖子。如果该线程返回wait
状态并且未再次调用notify
,则所有其他等待线程将保持等待,并且您自己陷入僵局。
使用notifyAll
将使wait
状态的所有线程都有机会继续。
notify
非常危险,几乎没有充分理由使用它。
更好的是,您为什么首先使用wait
/ notify
/ notifyAll
?你想要实现什么目标?无论你试图实现什么并发模式,都可能已经在java.util.concurrent
中实现了一个实现,它可以更清楚,更安全地完成你想做的任何事情。
答案 2 :(得分:0)
正如我在评论中所说,每个同步块中的第二个notify()
是可疑的。如果wait()
的目的是让你描述的两个线程轮流,那么只有一个在任何给定的时间运行,那么你的代码就会被破坏。以下是实际发生的事情:
readyLock
,如果有,则在当前线程释放该监视器时可以继续。readyLock
的监视器wait()
返回,与第一个主题同时运行。 就其本身而言,这并不能解释死锁,但如果你不希望这两个线程并发运行,那么就会出现任何麻烦。
以下是您可以更好地构建该方案的方法:
synchronized (readyLock) {
setMyTurn(false);
otherPlayer.setMyTurn(true);
readyLock.notify();
while (!isMyTurn()) {
try {
readyLock.wait();
} catch (InterruptedException ex) {
Logger.getLogger(Battleship_server_clientThread.class.getName()).log(
Level.SEVERE, null, ex);
}
}
}
请注意,您可能需要考虑notifyAll()
而不是notify()
。如果监视器上只有一个其他线程正在等待,那么区别并不重要,但如果所有潜在的服务员都使用循环和条件检查,那么它会更安全。