Java 加斯顿和阿尔方斯的例子:如何进入弓背?

Java 加斯顿和阿尔方斯的例子:如何进入弓背?,java,anonymous-class,Java,Anonymous Class,我对这个例子总是有困难。这似乎是一种不必要的复杂方式来展示其试图实现的概念: 所以我的问题与同步或锁定无关;这可能与匿名类有关: 这只是如何访问bow方法中调用的bowBack中的代码?实现runnable的匿名类被传递给bow()方法 也许这是个糟糕的问题。但是,用匿名类说明死锁会给示例带来不需要的复杂性,这是对的吗?方法调用bowback;这就是你的意思吗?您问“如何访问bowback方法中调用的bowback中的代码”,我不确定您的其他意思…bow方法调用bowback;这就是你的意思吗

我对这个例子总是有困难。这似乎是一种不必要的复杂方式来展示其试图实现的概念:

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

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


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

方法调用
bowback
;这就是你的意思吗?您问“如何访问bowback方法中调用的bowback中的代码”,我不确定您的其他意思…

bow方法调用
bowback
;这就是你的意思吗?您会问“bowback中在bow方法中调用的代码是如何访问的”,我不确定您还想说什么…

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

alphonse.bow(gaston)
gaston.bow(alphonse)

bow
方法依次调用具有调用效果的
bower.bowBack(this)

gaston.bowBack(alphonse)
第二个匿名内部类的
run
方法调用

alphonse.bow(gaston)
gaston.bow(alphonse)
最后是什么

alphonse.bowBack(gaston)
在考虑到两个
Runnable
实例由不同的线程运行,并且
bow
bowBack
方法是同步的之前,这些都不是很有趣的。因此,我们的情况如下:

  • 第一根线
    • 呼叫
      alphonse.bow
      ,锁定alphonse
    • 打电话给加斯顿。后弓,把门锁在加斯顿身上
  • 第二线
    • 打电话给加斯顿。船头,把门锁在加斯顿身上
    • 呼叫
      alphonse.bowBack
      ,锁定alphonse
  • 或者,更简洁地说:

  • 第一条线锁定阿尔方斯,然后锁定加斯顿
  • 第二条线锁定加斯顿,然后锁定阿尔方斯
  • 这很容易导致这样一种情况:第一个线程已经锁定了alphonse,第二个线程已经锁定了gaston,两个线程都无法继续,因为它正在等待另一个线程持有的锁。这就是本例所说明的死锁

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

    匿名内部类的替代方法(同样,在Java8之前)是使用命名类。这会给示例增加混乱,我不认为这会让它更容易理解。(再说一次,我对匿名内部类很满意。)

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

    new Thread(() -> alphonse.bow(gaston)).start();
    new Thread(() -> gaston.bow(alphonse)).start();
    
    这使示例更加简洁,尽管如果您不熟悉lambdas,这可能没有帮助

    目前,对于本例来说,使用匿名内部类是在不同线程上运行代码的合理方式


    很难想出有效的方法来简化这个例子。目前,两个线程、两个对象和两个方法调用具有相当令人满意的对称性。主线程对单个子线程的死锁是可能的,但这会破坏对称性。也可以让两个线程死锁调用不同对象上的单个方法。这将使示例变得更短,但可能会令人困惑,因为单个方法将被调用四次:在两个对象上调用一次,从两个线程中调用一次。它可能更难理解,也更难解释。

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

    alphonse.bow(gaston)
    
    gaston.bow(alphonse)
    

    bow
    方法依次调用具有调用效果的
    bower.bowBack(this)

    gaston.bowBack(alphonse)
    
    第二个匿名内部类的
    run
    方法调用

    alphonse.bow(gaston)
    
    gaston.bow(alphonse)
    
    最后是什么

    alphonse.bowBack(gaston)
    
    在考虑到两个
    Runnable
    实例由不同的线程运行,并且
    bow
    bowBack
    方法是同步的之前,这些都不是很有趣的。因此,我们的情况如下:

  • 第一根线
    • 呼叫
      alphonse.bow
      ,锁定alphonse
    • 打电话给加斯顿。后弓,把门锁在加斯顿身上
  • 第二线
    • 打电话给加斯顿。船头,把门锁在加斯顿身上
    • 呼叫
      alphonse.bowBack
      ,锁定alphonse
  • 或者,更简洁地说:

  • 第一条线锁定阿尔方斯,然后锁定加斯顿
  • 第二条线锁定加斯顿,然后锁定阿尔方斯
  • 这很容易导致这样一种情况:第一个线程已经锁定了alphonse,第二个线程已经锁定了gaston,两个线程都无法继续,因为它正在等待另一个线程持有的锁。这就是本例所说明的死锁

    现在您询问了匿名内部类。其中一个要点是,有多个线程在对象和锁上交互。如果只有一个线程,就不会死锁。如何让代码在另一个线程上运行?最简单的方法是创建一个线程,并向其传递一个
    Runnable
    的实例,其
    run
    方法在新创建的线程上执行。最简洁的方式