【问题标题】:If a method is synchronized, do the called methods also have to be synchronized?如果一个方法是同步的,那么被调用的方法是否也必须同步?
【发布时间】:2021-08-05 09:07:38
【问题描述】:

如果一个方法是同步的,被调用的方法是否也必须同步?下面的例子中什么是正确的?

// Only parent method synchronized 
public synchronized void parentMethod() {
    childMethod1();
}

public void childMethod1() {
    childMethod2();
}

public void childMethod2() {
    
}



// All methods synchronized 
public synchronized void parentMethod() {
    childMethod1();
}

public synchronized void childMethod1() {
    childMethod2();
}

public synchronized void childMethod2() {
    
}

【问题讨论】:

  • 取决于您的用例。 childMethod1 和 childMethod2 是否只能从 parentMethod 调用,或者它们也可以从其他调用者调用,并且在调用时需要同步?毕竟方法是公开的。
  • 如果 childmethod 是私有的,答案可能会有所不同。它是按设计公开的吗?
  • 任何保护非线程安全资源的方法都需要同步或使用其他形式的顺序化除非可以证明这已经在上游完成。需要分析。没有单一的答案。

标签: java concurrency thread-safety


【解决方案1】:

如果一个方法是同步的,被调用的方法是否也必须同步?

没有。

没有一般理由需要从另一个synchronized 方法调用synchronized 方法。

假设方法在同一个对象上同步,那么所有模式都是有效的,具体取决于您要实现的目标:

  • synchronized 方法调用synchronized 方法
  • 从普通方法调用synchronized 方法
  • synchronized 方法调用普通方法
  • 从普通方法调用普通方法

除了最后一种情况,被调用的方法都将持有目标对象的锁。

(在第一种情况下,看起来好像线程要访问同一个对象两次。实际上,Java 原始锁是可重入的……所以这不是问题。)


如果方法调用在不同目标对象上,它会变得有点复杂。现在您必须考虑您的应用程序是否需要锁定两个对象。您还需要考虑死锁的可能性。 (如果两个线程尝试同时获取相同的两个原始锁,但顺序不同,则会出现死锁。)


实际上不可能给出关于哪些方法需要同步1的硬性规则。这取决于方法的作用,以及您是使用原始锁互斥锁还是其他机制(Lockvolatile、不可变类型等)来同步和/或确保内存可见性。即使对于原始锁互斥体,您也可以使用synchronized 块的synchronized 方法来实现相同的目的。


1 - 请注意,问题无论如何都不会问这个!

【讨论】:

  • 只是一个小评论。正如这个答案中提到的,不需要将第二种方法声明为已同步,但如果您要更新其中的共享资源,您要么确保调用该方法的所有方法都是同步的,要么您也必须同步该方法。
  • 比这复杂得多。这个问题太复杂了……而且超出了问题的范围。
猜你喜欢
  • 2014-01-29
  • 2012-03-20
  • 2011-08-13
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 2012-03-13
  • 2018-04-13
  • 1970-01-01
相关资源
最近更新 更多