死锁和同步方法 [英] Deadlocks and Synchronized methods

查看:134
本文介绍了死锁和同步方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've found one of the code on Stack Overflow and I thought it is pretty similar to what I am facing but I still don't understand why this would enter a deadlock. The example was taken from Deadlock detection in 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();
  }
}

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

In this case, when the Deadlock() constructor is called, it starts itself as a thread. When it does this, the run() method is invoked. It will call b.methodB(a), which then calls a.last() to just print out a statement. At the same time, a.methodA(b) would call b.last(). There is no cross dependencies on any object and they are not executing a method at a same time too. Even if they are, the synchronized keyword would queue them, wouldn't it? But how come this would occasionally enter a deadlock too? It is not all the time but it would sometimes enter a deadlock, which is quite unpredictable. What is it that causes this to go into a deadlock and workarounds?

推荐答案

这两个陈述的执行可能是交织:

It is possible that the execution of these two statements is interweaved:

Thread 1:  a.methodA(b);    //inside the constructor
Thread 2:  b.methodB(a);    //inside run()

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

to execute a.methodA(), Thread 1 will need to obtain the lock on the A object.

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

to execute b.methodB(), Thread 2 will need to obtain the lock on the B object.

对于线程1的方法A()然后能够在 b 实例,它需要获取线程2持有的 b 的锁,这将导致线程1等待,直到释放该锁。

For Thread 1's methodA() to then be able to call the sychronized method on the b instance, it will need to obtain the lock on b being held by Thread 2, which will cause Thread 1 to wait until that lock is freed.

对于Thread2的 methodB(),可以在 a 实例,它需要获取由线程1保存在 a 上的锁定 - 这将导致线程2也等待。

For Thread2's methodB() to be able to call the synchronized method on the a instance, it will need to obtain the lock being held on a by Thread 1 - which will cause Thread 2 to wait as well.

由于每个线程都持有另一个线程想要的锁,因此会发生死锁,其中任何一个线程都无法获得所需的锁,并且两个线程都不会释放该loc 持有的ks。

Since each thread is holding a lock that the other thread wants, a deadlock will occur where neither thread is able to obtain the lock it wants, and neither thread will release the locks that it does hold.

重要的是要理解这段代码在运行它时不会产生死锁 - 只有当四个关键步骤(Thread1持有A的锁并试图获得B,其中线程2持有B的锁并尝试获得A)时,按特定顺序执行。运行此代码足够多次,但订单肯定会发生。

It's important to understand that this code will not produce a deadlock 100% of the time you run it - only when the four crucial steps (Thread1 holds A's lock and tries to obtain B, which Thread 2 holds B's lock and tries to obtain A's) are executed in a certain order. Run this code enough times and that order is bound to happen though.

这篇关于死锁和同步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆