Java中的死锁:何时发生?

Alb*_*ore 10 java synchronization deadlock java-me

我正在为J2ME开发一个应用程序,有时完全冻结,AMS关闭它需要相当长的时间.在我看来,这似乎是一个死锁问题.

你能告诉我什么可能导致死锁吗?例如,调用对象的同步方法会导致死锁,如果它调用自己的另一个同步方法吗?

谢谢!


更新

我是否正确地说在以下情况下应该发生死锁:

对象P调用对象A的synch方法,该方法调用对象B的synch方法,该方法调用对象A的synch方法

对不起,如果它看起来很愚蠢,很可能就是这样.但这就是我要问的原因.谢谢!

Pét*_*rök 12

例如,调用对象的同步方法会导致死锁,如果它调用自己的另一个同步方法吗?

不,因为synchronizedJava中的锁是可重入的:您可以多次从同一个线程获取相同的锁而没有问题.

发生死锁,例如当线程A持有锁L并尝试获取锁M时,而线程B持有锁M并尝试获取锁L.因此两个线程都在等待另一个持有的锁,并且无法继续释放它们自己的锁.这导致两个线程永远等待.这种情况也可能涉及2个以上的线程.

死锁可能非常难以检测,因此典型的方法是通过精心设计来避免死锁.实现此目的的最简单方法是确保获取多个锁的任何线程始终以相同的预定义全局顺序获取它们.例如,如果在上面的例子中,线程A和B都先尝试获取锁L,那么锁M,就不会有死锁.

您的问题也可能是由死锁之外的其他因素引起的,例如活锁(当一个线程未被阻塞时,仍然无法继续进行,因为它一直在重试一个总是失败的操作).

更新:从对象外部访问锁

使用Java内部锁(即synchronized块),底层Lock对象本身在代码中不可见,只有我们锁定的对象.考虑

class MyClass {
  private Object object = new Object();

  public synchronized void synchronizedOnThis1() {
    ...
  }
  public void synchronizedOnThis2() {
    synchronized(this) {
      ...
    }
  }
  public void synchronizedOnPrivateObject() {
    synchronized(object) {
      ...
    }
  }
}

class ExternalParty {
  public void messUpLocks() {
    final MyClass myObject = new MyClass();
    synchronized(myObject) {
      Thread otherThread = new Thread() {
        public void run() {
            myObject.synchronizedOnThis1();
        }
      };
      otherThread.start();
      // do a lengthy calculation - this will block the other thread
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这两个synchronizedOnThis*方法都在包含MyClass实例上同步; 这两种方法的同步是等价的.但是,外部世界显然可以访问类实例,因此外部方可以将其用作类外部的锁,如上所示.如果该对象可以从另一个线程访问,并且该线程调用其中一个synchronizedOnThis*方法,则只要该线程在synchronized(myObject)块内,该调用就会阻塞.

OTOH方法synchronizedOnPrivateObject使用私有对象作为锁.如果该对象没有以任何方式发布给外部各方,则其他任何人都无法(无意中或恶意地)导致涉及此锁定的死锁.