每当出现关于Java同步的问题时,一些人都会非常急切地指出应该避免synchronized(this)。相反,他们声称,最好是锁定私有引用
其中一些原因是:
- 某些邪恶代码可能会偷走您的锁(此代码非常流行,也有“意外”变体)
- 同一类中的所有同步方法使用完全相同的锁,这会降低吞吐量
- 您(不必要地)暴露了太多信息
包括我在内的其他人认为,synchronized(this)是一个经常使用的习惯用法(也在Java库中使用),是安全的,并且很容易理解。这是不应该避免的,因为您有一个bug,并且您不知道多线程程序中发生了什么。换句话说:如果它是适用的,那么就使用它
我感兴趣的是看到一些真实世界的例子(没有foobar的东西),当synchronized(this)也能起作用时,避免锁定this是更好的选择
因此:您是否应该始终避免同步(this)并将其替换为对私有引用的锁定?
一些进一步的信息(随着给出的答案而更新):
- 我们正在讨论实例同步
- 同时考虑了隐式(
synchronized方法)和显式形式的synchronized(this) - 如果您引用Bloch或其他权威人士的话,不要遗漏您不喜欢的部分(例如,有效Java、线程安全项目:通常是实例本身的锁,但也有例外。)
- 如果除了
synchronized(此)提供的锁定之外,您还需要粒度,那么synchronized(此)不适用,因此这不是问题所在
我将分别讨论每一点
-
一些邪恶的代码可能会偷走你的锁(非常流行这一个,也有一个
“意外”变体)我更担心的是意外的。这意味着,
this的使用是类的公开接口的一部分,应该记录在案。有时需要其他代码使用您的锁。这适用于Collections.synchronizedMap(请参阅javadoc) -
同一类中的所有同步方法使用完全相同的
锁,这会降低吞吐量这是过于简单化的想法;仅仅摆脱
synchronized(这个)并不能解决问题。适当的吞吐量同步需要更多的考虑 -
你(不必要地)暴露了太多的信息
这是#1的一个变体。使用
synchronized(此)是界面的一部分。如果你不想/不需要暴露,不要这样做