0

これはJavaの複製ではなく、同期されたメソッドを使用したマルチスレッド化です...彼は同じ質問をしませんでした。

マルチスレッドとデッドロックを使用するプログラムを作成しようとしています。同期されたメソッドで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);  
    }
}

Deadlock.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();
   }
}
4

2 に答える 2

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て通知します。
  • 次に、2番目のスレッドロックがロックbを試みaて通知します。

各スレッドにはロックがありますが、続行するには他のロックが必要です。古典的なデッドロック。

デバッガー@OhioState22の使用法を学ぶことをお勧めします。ブレークポイントを設定し、コードをステップスルーします。これがまともなEclipseチュートリアルです。

于 2013-01-18T00:16:30.537 に答える
0

原則として、Javaのwait()とnotify()の使用を避け、代わりにJava5の同時実行機能の1つ(ReentrantLockなど)を優先します。その理由は、スレッドがwait()にヒットする前にスレッドがnotify()を呼び出すと、後続のwait()の呼び出しがブロックされ、アルゴリズムによっては無期限にブロックされるためです。RenetrantLockのjavadocsを検索します

于 2013-01-18T00:51:19.817 に答える