具有死锁的多线程

时间:2014-07-04 21:00:43

标签: java multithreading

在java教程中我来到了这个简单的死锁示例,由于某种原因无法弄清楚为什么会阻塞

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("%s: %s"
                + "  has bowed to me!%n", 
                this.name, bower.getName());
            System.out.println("Nice try " + this.name);
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}

让我们看看一些真实的例子

run:
Alphonse: Gaston  has bowed to me!
Gaston: Alphonse  has bowed to me!
Nice try Gaston
Nice try Alphonse

所以Alphonse和Gaston,现在正在运行“bow()”,每个人在“bow()”的末尾试图互相调用“bowBack()”,“bowBack()”并不是静止的,因此Alphonse和Gaston已经分离了这个方法的实例,之前也没有调用“bowBack()”,因此它不应该被阻塞。那么为什么这是一个僵局。

在教程中 http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

它被解释为

When Deadlock runs, it's extremely likely that both threads will block when they 
attempt to invoke bowBack. Neither block will ever end, because each thread is 
waiting for the other to exit bow.

但是为什么要运行“bowBack()”它应该先等待“bow()”的结束,如果它们不互相干扰

Alphonse.bow()--->试图打电话 - > Gaston.bowBack()

Gaston.bow()--->试图调用 - > Alphonse.bowBack()

1 个答案:

答案 0 :(得分:2)

  

但是为什么要运行“bowBack()”它应该先等待“bow()”的结束,如果它们不互相干扰

调用bowBack()时 - 正在运行的线程尝试获取的锁定是Object锁定其尝试调用的方法。

这里 - Alphonse是一个对象,Gaston是第二个对象。

Alphonse.bow()--->试图打电话 - > Gaston.bowBack()

在上面,第一次调用锁定了Alphonse,当仍然保持锁定时,尝试锁定Gaston。

因此,在线程1:锁定(Alp)并尝试锁定(加斯顿)而不释放锁定(Apl)

Gaston.bow()--->试图调用 - > Alphonse.bowBack()

在这里,第一个bow()获取对Gaston对象的锁定,然后尝试获取对Alphonse的锁定。

所以,在线程2:锁定(加斯顿)并尝试锁定(Apl)而不释放锁定(加斯顿)

如果线程1和线程2中的第一步都完成了,那么你可以看出第二步永远无法完成 - 因此死锁