请帮助我理解这个死锁示例

Dom*_*ino 0 java multithreading deadlock

对于我的编程语言类,我们已经获得了一个简单的Java死锁示例,并被要求解决它.我不直接想要这个问题的答案,我主要想知道我的理解缺乏的地方.这是代码:

import java.applet.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

// Attempt at a simple handshake.  Girl pings Boy, gets confirmation.
// Then Boy pings girl, get confirmation.
class Monitor {
   String name;

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

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

   // Girl thread invokes ping, asks Boy to confirm.  But Boy invokes ping,
   // and asks Girl to confirm.  Neither Boy nor Girl can give time to their
   // confirm call because they are stuck in ping.  Hence the handshake 
   // cannot be completed.
   public synchronized void ping (Monitor p) {
      System.out.println(this.name + " (ping): pinging " + p.getName());
      p.confirm(this);
      System.out.println(this.name + " (ping): got confirmation");
   }

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

class Runner extends Thread {
   Monitor m1, m2;

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

   public void run () {
      //System.out.println(m1.getName() + " about to ping " + m2.getName());
      m1.ping(m2);
   }
}

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();
   }
}
Run Code Online (Sandbox Code Playgroud)

当我执行上面的代码时,我相信每次都会发生以下情况(虽然它没有,因为有时我们会死锁):

女孩ping男孩,把锁放在ping()方法上.女孩,里面ping(),试图打电话boy.confirm().男孩的confirm()答案,因此把我们带回到Girl.ping()它完成的地方,取消了锁定ping(),而Boy的实例完全相同.使用所有锁定,似乎整个程序被序列化,从而破坏了多线程的目的?无论如何,我通常会得到以下输出

Starting...1
Girl (ping): pinging Boy
Boy (confirm): confirm to Girl
Girl (ping): got confirmation
Boy (ping): pinging Girl
Girl (confirm): confirm to Boy
Boy (ping): got confirmation
Run Code Online (Sandbox Code Playgroud)

但是有时我们会遇到死锁,输出变为:

Girl (ping): pinging Boy
Boy (ping): pinging Girl
Run Code Online (Sandbox Code Playgroud)

我不明白我们怎么能进入这种状态,因为看起来ping()我们第一次进去的时候就锁定了这个方法,所以ping()如果女孩已经在使用它,男孩怎么会打电话呢?被女孩试图调用boy.confirm()时,男孩正忙呼ping()

Mar*_*nik 5

您的ping方法是同步的,并采取上的锁this,那么它前进到呼叫confirmp,从而试图夺取其锁定为好.步骤:

  1. "女孩"线程获取Boy对象锁定,进入ping;
  2. "男孩"线程获取Girl对象的锁定,进入ping;
  3. 女孩想打电话Boy.confirm,等待锁;
  4. 男孩想打电话Girl.confirm,等待锁;
  5. 僵局.