死锁和同步方法

Car*_*ven 5 java multithreading synchronization deadlock

我在Stack Overflow上找到了一个代码,我认为它与我所面临的非常相似但我仍然不明白为什么会进入死锁状态.该示例取自Java中的死锁检测:

Class A
{
  synchronized void methodA(B b)
  {
    b.last();
  }

  synchronized void last()
  {
    System.out.println(“ Inside A.last()”);
  }
}

Class B
{
  synchronized void methodB(A a)
  {
    a.last();
  }

  synchronized void last()
  {
    System.out.println(“ Inside B.last()”);
  }
}

Class Deadlock implements Runnable 
{
  A a = new A(); 
  B b = new B();

  // Constructor
  Deadlock()
  {
    Thread t = new Thread(this); 
    t.start();
    a.methodA(b);
  }

  public void run()
  {
    b.methodB(a);
  }

  public static void main(String args[] )
  {
    new Deadlock();
  }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,当调用Deadlock()构造函数时,它将自己作为一个线程启动.执行此操作时,将调用run()方法.它将调用b.methodB(a),然后调用a.last()来打印出一个语句.同时,a.methodA(b)将调用b.last().任何对象都没有交叉依赖关系,并且它们也没有同时执行方法.即使它们是,synchronized参数也会排队,不是吗?但是为什么偶尔也会陷入僵局呢?它不是所有的时间,但它有时会进入僵局,这是非常不可预测的.是什么导致这种情况陷入僵局和变通办法?

mat*_*t b 19

这两个语句的执行可能是交织的:

Thread 1:  a.methodA(b);    //inside the constructor
Thread 2:  b.methodB(a);    //inside run()
Run Code Online (Sandbox Code Playgroud)

要执行a.methodA(),线程1将需要获取A对象的锁定.

要执行b.methodB(),线程2将需要获取B对象的锁定.

对于线程1 methodA(),然后能够在b实例上调用sychronized方法,它将需要获得b由线程2保持的锁定,这将导致线程1等待,直到释放该锁定.

为了使Thread2 methodB()能够在a实例上调用synchronized方法,它将需要获得a由线程1 保持的锁定- 这将导致线程2也等待.

因为每个线程持有另一个线程需要的锁,就会发生死锁,其中两个线程能够获得它想要的锁,两个线程将释放它的锁持有.

重要的是要理解这个代码在运行它时不会产生100%的死锁 - 只有当四个关键步骤(Thread1持有A的锁并试图获得B,线程2持有B的锁并试图获得A)时按特定顺序执行.运行此代码足够多次,但该命令必然会发生.

  • 这就是答案,但是我们什么时候才能在SO上画图呢?:-) (2认同)