如果我有同步的公共方法和私有方法:
public synchronized void doSomething() {
doSomethingElse()
}
private void doSomethingElse() {
}
我是否需要同步私有方法?
答案 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)
如果您同步一段代码,那么从该代码块(在同一个线程上)调用的任何内容仍然保持初始锁定。因此doSomethingElse
从doSomething
调用时仍然是同步块的一部分。
如果你这样做了:
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关键字添加到私有方法没有任何害处。
将代码置于私有方法中会让其它方法调用它,因此将私有方法同步以备将来从另一个方法调用它是有意义的,否则需要同步。