gpt4 book ai didi

java - 加斯顿和阿尔方斯示例 : How does the bowBack get accessed?

转载 作者:行者123 更新时间:2023-12-01 08:02:02 24 4
gpt4 key购买 nike

我一直对这个例子感到困惑。这似乎是不必要的复杂方式来展示它试图表达的概念:

http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

所以我的问题与同步或锁定无关;它可能与匿名类有关:

那么bow方法中调用的bowBack中的代码是如何访问的呢?实现 runnable 的匿名类被传递给 Bow() 方法。

也许这是一个糟糕的问题。但是,用匿名类来说明死锁会给示例带来不必要的复杂性,我这样说对吗?

最佳答案

第一个匿名内部类的 run 方法调用

alphonse.bow(gaston)

bow方法依次调用bower.bowBack(this),其效果是调用

gaston.bowBack(alphonse)

第二个匿名内部类的run方法调用

gaston.bow(alphonse)

最终调用

alphonse.bowBack(gaston)

这一切都不是很有趣,除非您考虑到两个 Runnable 实例由不同的线程运行,并且 bowbowBack code> 方法是同步的。因此我们会遇到以下情况:

  1. 第一个线程
    • 调用 alphonse.bow,锁定 alphonse
    • 调用 gaston.bowBack,锁定 Gaston
  2. 第二个线程
    • 调用 gaston.bow,锁定 Gaston
    • 调用 alphonse.bowBack,锁定 alphonse

或者,更简洁地说:

  1. 第一个线程锁定 alphonse,然后锁定 Gaston
  2. 第二个线程锁定 Gaston,然后锁定 alphonse

这很容易导致第一个线程获取了 alphonse 的锁,第二个线程获取了 Gaston 的锁,并且两个线程都无法继续,因为它正在等待获取另一个线程持有的锁。这就是本示例所说明的死锁。

现在您询问了匿名内部类。其中的一个要点是,有多个线程通过对象和锁进行交互。如果只有一个线程,这不会死锁。如何让代码在另一个线程上运行?最简单的方法是创建一个线程并向其传递一个 Runnable 实例,该实例的 run 方法在新创建的线程上执行。创建 Runnable 最简洁的方法(至少在 Java 8 之前)是使用匿名内部类。

匿名内部类的替代方案(同样是在 Java 8 之前)是使用命名类。这会给示例增加困惑,并且我认为这不会使其更容易理解。 (话又说回来,我对匿名内部类非常满意。)

Java 8 的替代方案是使用 lambda 代替匿名内部类:

new Thread(() -> alphonse.bow(gaston)).start();
new Thread(() -> gaston.bow(alphonse)).start();

这使得示例更加简洁,但如果您不熟悉 lambda,它可能没有帮助。

就目前情况而言,对于本示例来说,使用匿名内部类是让代码在不同线程上运行的合理方法。

很难想出有效的方法来使示例更简单。就目前情况而言,两个线程、两个对象和两个方法调用具有相当令人满意的对称性。主线程可能会对单个子线程产生死锁,但这会破坏对称性。调用不同对象上的单个方法也可能导致两个线程死锁。这将使示例更短,但可能会造成困惑,因为该单个方法将被调用四次次:从两个线程中的每一个线程,在两个对象中的每一个上调用一次。这可能更难理解,也更难解释。

关于java - 加斯顿和阿尔方斯示例 : How does the bowBack get accessed?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24718676/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com