同步方法

时间:2011-03-30 18:10:12

标签: java multithreading concurrency

如果我有同步的公共方法和私有方法:

public synchronized void doSomething() {
    doSomethingElse()
}

private void doSomethingElse() {
}

我是否需要同步私有方法?

9 个答案:

答案 0 :(得分:15)

取决于:

  • 如果同时调用doSomethingElse是安全的,那么您不需要synchronized
  • 如果不是,那么答案取决于它的调用位置:
    • 如果仅从其他synchronized方法调用它,则不需要synchronized(但将其标记为不会造成伤害);
    • 如果可以从不是synchronized的方法调用它,那么它必须synchronized

答案 1 :(得分:5)

这取决于你在做什么。您是否需要确保对doSomethingElse()的串行访问?

如果是这样,并且唯一调用doSomethingElse()的是doSomething(),那么不,您不需要同步。但是如果其他一些方法可以调用doSomethingElse(),那么是的,你也应该同步它。

答案 2 :(得分:4)

NO:如果调用doSomethingElse()的唯一方法是通过另一个IS同步的方法。

可能是:如果您以其他方式通过未同步的方法调用doSomethingElse(),则需要保护其免受并发访问。

答案 3 :(得分:2)

这是@GuardedBy注释的意图。如果您希望在调用该方法时保持锁必须,请使用它和锁的名称对其进行注释(在示例中它将是:

@GuardedBy("this") private void doSomethingElse() {…}

然后你可以检查FindBugs的不变量是否为真。

您也可以使用other net.jcip.annotations来描述线程安全性或缺少线程安全性,并让FindBugs验证这些假设。当然,the book也需要插件。

答案 4 :(得分:1)

从同步方法(或从synchronized块中)调用的任何方法在仍然同步的情况下运行。如果仅从同步方法调用私有方法,则无需单独同步私有方法。

答案 5 :(得分:0)

如果您同步一段代码,那么从该代码块(在同一个线程上)调用的任何内容仍然保持初始锁定。因此doSomethingElsedoSomething调用时仍然是同步块的一部分。

如果你这样做了:

public synchronized void doSomething() {
  new Thread() {
    public void run() {
      doSomethingElse();
    }
  }.start();
}
private void doSomethingElse() {
}

然后doSomethingElse 拥有doSomething获取的锁定。

还要避免使用同步方法,因为它会公开并发策略的实现细节。请参阅有关synchronized(this)/ synchronized方法的问题:Avoid synchronized(this) in Java?

如果必须同步doSomethingElse,无论是否从doSomething调用doSomethingElse,同步{{1}}都不会因为同步锁重入(即,如果一个线程已经锁定了一个对象,它就可以再次获得锁定。

答案 6 :(得分:0)

就个人而言,我不喜欢同步方法。我喜欢与某种锁定变量同步,如下:

private final Object lock = new Object();

public void doSomething() {
  synchronized(lock) {
    // Do some safely
    doSomethingElse();
  }
  // Do some work un-safely
}

private void doSomethingElse() {
  // Do some work safely because still in lock above
  // ...
}

答案 7 :(得分:0)

虽然您所做的很好,但在我看来,同步应尽可能以最低的粒度进行。这将建议同步实际的私人功能。目前,您假设类中没有其他函数可以独立调用私有函数。将来情况可能并非如此。

答案 8 :(得分:0)

即使代码在私有方法未同步时正常工作,从可维护性角度来看,使私有方法同步似乎也是谨慎的。

内部锁是可重入的,将synchronized关键字添加到私有方法没有任何害处。

将代码置于私有方法中会让其它方法调用它,因此将私有方法同步以备将来从另一个方法调用它是有意义的,否则需要同步。