java - 多线程死锁

标签 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()

最佳答案

but why, to run "bowBack()" it should first wait the end of the "bow()", if they don't interfere with each other

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

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

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

在上面,第一个调用锁定了 Alphonse,并在该锁定仍保持的同时尝试获取 Gaston 的锁定。

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

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

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

因此,在线程 2 中:锁定 (Gaston) 并尝试锁定(Apl),而不释放锁定(Gaston)

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

关于java - 多线程死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24580686/

相关文章:

java - 在多线程 Java 程序中,每个线程是否都有自己的 System.out 副本?

java - Java中无法分割字符串

java - 在 Android Instrumentation 测试中使用 PowerMock 和 Mockito - 错误 - 重复文件 - org.mockito.plugins.MockMaker

java - 处理: "magic"函数如何工作

c++ - 正在访问指针元组的元组和线程安全的互斥锁

c++ - 错误 : expected unqualified-id while using boost mutex

java - JPanel 中的多个动画(线程)

Python SARIMA 模型自动使用 CPU 的所有核心。如何?

java - Thread 中的 join() 方法是否保证完美工作,还是也依赖于各个 JVM?

java - 使用 spock 数据表填充对象