java 同步方法递归调用自身。这是坏了吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13197756/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 11:50:28  来源:igfitidea点击:

Synchronized method calls itself recursively. Is this broken?

javarecursionsynchronized

提问by Thom

The point of this question is to illustrate that Java is not working as I expected.

这个问题的重点是说明 Java 没有按我预期的那样工作。

How would you expect the following code to behave?

您希望以下代码的行为如何?

public class SynchTester {
  private static SynchTester synchTester;

  public synchronized static SynchTester getSynchTester(){
    if(synchTester==null){
      synchTester = new SynchTester();
    }

    return synchTester;
  }

  private SynchTester() {
    SynchTester myTester = getSynchTester();
  }

  public static void main(String[] args) {
    SynchTester tester = SynchTester.getSynchTester();
  }
}

I would expect it to hang with a deadlock waiting on the recursion to complete, but instead it throws StackOverflow. Evidently synchronized does not block access to the same thread.

我希望它挂起等待递归完成的死锁,但它会抛出 StackOverflow。显然同步不会阻止对同一线程的访问。

Is this a bug?

这是一个错误吗?

回答by Duncan Jones

In Java, synchronized locks are reentrant.

在 Java 中,同步锁是可重入的

Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.

回想一下,一个线程不能获得另一个线程拥有的锁。但是一个线程可以获得一个它已经拥有的锁。允许一个线程多次获取同一个锁可以实现可重入同步。这描述了一种情况,即同步代码直接或间接调用了一个也包含同步代码的方法,并且两组代码使用相同的锁。如果没有可重入同步,同步代码将不得不采取许多额外的预防措施来避免线程导致自身阻塞。

Source: see bottom of this page

来源:见本页底部

回答by akaIDIOT

A synchronized method needs to be able to get a lock on the monitor object. The monitor object is the instance (or class for a static method). A thread that already has the lock does not need to get it again. So yes, that could cause a stackoverflow (harhar).

同步方法需要能够获得监视器对象的锁定。监视器对象是实例(或静态方法的类)。已经拥有锁的线程不需要再次获取它。所以是的,这可能会导致计算器溢出(harhar)。

回答by Luca Putzu

from the java tutorials:

来自java教程

When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.

当一个线程正在为一个对象执行同步方法时,所有其他调用同一对象的同步方法的线程都会阻塞(挂起执行),直到第一个线程完成对对象的处理。

So I think the syncronized keyword worked as expected, and a synchronized recursive call is perfectly legal (and working) in java.

所以我认为 syncronized 关键字按预期工作,并且同步递归调用在 java 中是完全合法的(并且有效)。