【问题标题】:Java - using wait() and notify()Java - 使用 wait() 和 notify()
【发布时间】:2013-01-17 23:51:15
【问题描述】:

这不是Java, Multithreading with synchronized methods 的重复...他没有问同样的问题。

我正在尝试编写一个使用多线程和死锁的程序。我无法理解在同步方法中如何以及在何处使用 wait() 和 notify() 以使线程等待并使用 notify() 将其唤醒。我有它让第一个线程在 ping 语句之后等待,以便下一个线程也将启动它的 ping 语句。但是我有一个 notify() 来唤醒第一个线程,但我不知道为什么线程不会唤醒。以下是我的输出:

Starting...1
Girl (ping): pinging Boy
Boy (ping): pinging Girl
Girl (ping): asking Boy to confirm
Boy (confirm): confirm to Girl
Girl (ping): got confirmation
Boy (ping): asking Girl to confirm
Girl (confirm): confirm to Boy
Boy (ping): got confirmation

我的代码死锁了,或者我没有正确使用等待和通知,因为它停在这里:

Starting...1
Girl (ping): pinging Boy
Boy (ping): pinging Girl
Girl (ping): asking Boy to confirm
Boy (confirm): confirm to Girl
Girl (ping): got confirmation

这是我的代码:

Monitor.java

class Monitor {
String name;

   public Monitor (String name) { this.name = name; }

   public String getName() {  return this.name; }

   public synchronized void ping (Monitor p) {
      p.release(p);
      System.out.println(this.name + " (ping): pinging " + p.getName());
      notify();
      try { wait(); } catch (Exception e) {}
      System.out.println(this.name + " (ping): asking " + p.getName() + " to confirm");
      p.confirm(p);
      System.out.println(this.name + " (ping): got confirmation");
   }

   public synchronized void confirm (Monitor p) {
      System.out.println(this.name + " (confirm): confirm to " + p.getName());
   }

   public synchronized void release (Monitor p) {
      notify();
   }
}

Runner.java

public class Runner extends Thread {
Monitor m1, m2;

    public Runner (Monitor m1, Monitor m2) { 
      this.m1 = m1; 
      this.m2 = m2; 
    }

    public void run () {  
       m1.ping(m2);  
    }
}

死锁.java

public class DeadLock {
   public static void main (String args[]) {
      int i=1;
      System.out.println("Starting..."+(i++));
      Monitor a = new Monitor("Girl");
      Monitor b = new Monitor("Boy");
      (new Runner(a, b)).start();
      (new Runner(b, a)).start();
   }
}

【问题讨论】:

  • A deadlock 是程序(或至少一些线程)停止运行,因为它们每个都在等待另一个释放资源。你确定你的意思是你希望你的程序有死锁吗?
  • 不,我不希望它陷入僵局,对不起,如果我有点罗嗦。我试图避免死锁,并让线程等待并使用通知唤醒以获得我想要的输出。
  • 代码很奇怪......我的意思是,在pingthis.notify()(因为线程没有等待而没有效果)然后this.wait() 停止线程。另一个线程也一样,所以两个线程最终都在等待另一个线程唤醒。你确定第一行不是synchronized (p) {p.notify();}wait 应该在同步块内,如果我是对的(现在有点太困了)。

标签: java multithreading deadlock


【解决方案1】:

你在打电话:

(new Runner(a, b)).start();
// which effectively calls in run()
a.ping(b);

这会锁定a 调用a 上的通知,然后等待a

其他线程调用:

(new Runner(b, a)).start();
// which effectively calls in run()
b.ping(a);

这会锁定b 调用b 上的通知,然后等待b

由于两个线程都没有通知另一个线程,它们永远不会离开那个状态。我不确定您要完成什么,因此很难弄清楚如何修复代码。

编辑:

现在你已经编辑了你的代码,你有一个更标准的死锁。

  • 第一个线程锁定a 然后尝试锁定b 以通知它。
  • 第二个线程锁定b 然后尝试锁定a 以通知它。

每个线程都有自己的锁,但需要另一个锁才能继续。经典的死锁。

我建议你学习使用调试器@OhioState22。设置断点并单步执行您的代码。这是一个不错的Eclipse tutorial

【讨论】:

  • 我试图让代码成为我上面列出的输出。我已经稍微修改了上面的代码,试图让线程工作,并能够让它打印到女孩得到确认的地方。我现在怎样才能让男孩确认女孩?
  • 我已经编辑了我的答案。你必须自己做一些工作。在你做对之前,你不能一直编辑你的答案。
【解决方案2】:

作为一项规则,避免使用 Java 的 wait() 和 notify() 而是更喜欢 Java 5 的并发特性之一,例如可重入锁。原因是如果一个线程在你的线程命中 wait() 之前调用 notify(),随后对 wait() 的调用将无限期地阻塞并且取决于你的算法。在 javadocs 中查找 RenetrantLock

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    相关资源
    最近更新 更多