首页 > 解决方案 > 如果一个方法是同步的,被调用的方法是否也必须同步?

问题描述

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

// 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() {
    
}

标签: javaconcurrencythread-safety

解决方案


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

不。

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

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

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

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

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


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


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


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


推荐阅读