DeadLock进程首先锁定哪一个?

时间:2012-11-26 10:11:24

标签: java concurrency

请考虑以下事项:

public class Deadlock {
static class Friend{
    private final String name;

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

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


    public synchronized void bow(Friend bower){
        System.out.format("\n%S: %S has bowed to me!" , this.name, bower.getName());
        bower.bowBack(this);
    }
    public synchronized void bowBack(Friend bower) {
        System.out.format("\n%S: %S has bowed back to me!", this.name, bower.getName());
    }


}

public static void main(String[] args) {
    final Friend alf = new Friend("Alf");
    final Friend arian = new Friend("Arian");

    // Thread 1
             new Thread(new Runnable()  {
        public void run(){ alf.bow(arian);}}).start();

    //Thread 2
    new Thread(new Runnable()  {
        public void run(){ arian.bow(alf);}}).start();  
}

}

输出是

ALF:ARIAN向我鞠躬致敬! ARIAN:ALF向我鞠躬!

锁定状况.....

当线程1运行时,它需要锁定对象Friend。紧接着线程2需要锁定第二个对象。现在方法 bow 被线程1锁定,因此打印出“ALF:ARIAN向我鞠躬!”。线程2如何进入 bow ,两者都不能输入 * bowBack * ??

关心B.

4 个答案:

答案 0 :(得分:5)

请注意,synchronized方法始终会在this上同步。

有两个对象,因此有两个锁。 alf.bow()获取alf锁,arian.bow()获取arian s。但是bowback()试图获取另一个,即发生死锁时。

如果要在共享锁对象上进行同步,则应该执行以下操作:

class Friend {
   private static final Object lock = new Object();

   public void bow(...) {
     synchronized( lock ) {
        ...
     }
   }

   public void bowback(...) {
     synchronized( lock ) {
        ...
     }
   }

}

由于lock在静态字段中,这意味着Friend的所有实例都使用相同的锁对象,因此不存在死锁的可能性。

您还可以在类对象synchronized( Friend.class ) {...}上进行同步,但在外部可见对象上进行同步通常不是一个好主意,因为无法保证代码的其他部分不会窃取锁定。

答案 1 :(得分:3)

使用任何对象完成同步;如果线程与不同的对象同步,则它们可以同步进入同步块中。

实例方法中的synchronized关键字表示该实例同步。由于您正在调用两个不同对象的bow方法,因此无法同时执行此类函数。

通过类对象进行同步(或使用为此目的创建的静态最终对象)。

答案 2 :(得分:1)

- 您使用了2 objects这里的线程都使用了2个不同的Monitor锁。

- 由于两个线程都在锁定2 different object,因此很明显,对象1上的线程1的锁定对线程2的锁定没有影响2。

- 您使用了synchronized关键字,这需要对象锁定,并且您为两个线程提供了自己的对象锁,因此线程2进入船头。

答案 3 :(得分:1)

您需要锁定一个公共对象。

public static void main(String[] args) {
    final Object lock = new Object();
    final Friend alf = new Friend("Alf", lock);
    final Friend arian = new Friend("Arian", lock);
    ...  
}


public  void bow(Friend bower){
    synchronize(lock){
        System.out.format("\n%S: %S has bowed to me!" , this.name, bower.getName());
        bower.bowBack(this);
    }
}
public void bowBack(Friend bower) {
    synchronize(lock){
        System.out.format("\n%S: %S has bowed back to me!", this.name, bower.getName());
    }
}