同步语句第二次不起作用

时间:2015-10-06 21:23:22

标签: java multithreading concurrency synchronization synchronized

更新 事实证明我的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("");这些行用于调试。

3 个答案:

答案 0 :(得分:3)

使用notify()时,会出现状态更改。

当你wait()时,你应检查状态变化。

否则你冒险;

  • 如果当时没有等待,notify就会丢失。
  • wait可以虚假地醒来。

这些方法的文档中对此进行了介绍。

答案 1 :(得分:0)

请勿使用notify,请使用notifyAllnotify会选择一个随机等待的帖子。如果该线程返回wait状态并且未再次调用notify,则所有其他等待线程将保持等待,并且您自己陷入僵局。

使用notifyAll将使wait状态的所有线程都有机会继续。

notify非常危险,几乎没有充分理由使用它。

更好的是,您为什么首先使用wait / notify / notifyAll?你想要实现什么目标?无论你试图实现什么并发模式,都可能已经在java.util.concurrent中实现了一个实现,它可以更清楚,更安全地完成你想做的任何事情。

答案 2 :(得分:0)

正如我在评论中所说,每个同步块中的第二个notify()是可疑的。如果wait()的目的是让你描述的两个线程轮流,那么只有一个在任何给定的时间运行,那么你的代码就会被破坏。以下是实际发生的事情:

  1. 一个线程进入(其中一个)同步块,不包括所有其他块。
  2. 该线程通知另一个阻止等待readyLock,如果有,则在当前线程释放该监视器时可以继续。
  3. 当前线程阻塞,释放监视器并等待其自己的通知。
  4. 另一个线程做了它的事情,直到它来到相同或类似的块,此时它通知等待的线程,然后它自己开始等待。
  5. 原始线程继续,立即通知等待线程。
  6. 原始线程退出synchronized块,释放readyLock的监视器
  7. 第二个主题可以从wait()返回,与第一个主题同时运行。
  8. 就其本身而言,这并不能解释死锁,但如果你不希望这两个线程并发运行,那么就会出现任何麻烦。

    以下是您可以更好地构建该方案的方法:

    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()。如果监视器上只有一个其他线程正在等待,那么区别并不重要,但如果所有潜在的服务员都使用循环和条件检查,那么它会更安全。