每当在 SO 上弹出有关 Java 同步的问题时,有些人会非常急切地指出 synchronized(this)
应该避免。相反,他们声称,首选锁定私有引用。
一些给出的原因是:
- 一些 恶意代码 可能会窃取你的锁(这个很受欢迎,也有一个“意外”变体)
- 同一类中的所有同步方法都使用完全相同的锁,这会降低吞吐量
- 你(不必要地)暴露了太多信息
包括我在内的其他人认为 synchronized(this)
是一个经常使用(也在 Java 库中)的惯用语,是安全且易于理解的。它不应该被避免,因为你有一个错误并且你不知道你的多线程程序中发生了什么。换句话说:如果它适用,那就使用它。
我有兴趣看到一些真实世界的例子(没有 foobar 的东西),其中避免锁定 this
是更可取的,而 synchronized(this)
也可以完成这项工作。
因此: 您是否应该始终避免 synchronized(this)
并将其替换为私有引用上的锁?
一些进一步的信息(根据给出的答案进行更新):
- 我们正在谈论实例同步
- 隐式(
synchronized
方法)和synchronized(this)
的显式形式都被考虑 - 如果您引用 Bloch 或其他有关该主题的权威,请不要遗漏您不喜欢的部分(例如 Effective Java,Thread Safety 上 的项目:通常是实例本身的锁,但也有例外。)
- 如果您需要锁定粒度而不是
synchronized(this)
提供,那么synchronized(this)
不适用,所以这不是问题
原文由 eljenso 发布,翻译遵循 CC BY-SA 4.0 许可协议
我将分别介绍每一点。
我更担心 _一不小心_。它相当于
this
的这种使用是您类的公开接口的一部分,应该记录在案。有时需要其他代码使用您的锁的能力。这对于像Collections.synchronizedMap
这样的事情是正确的(参见 javadoc)。这是过于简单化的想法;只是摆脱
synchronized(this)
不会解决问题。吞吐量的正确同步将需要更多考虑。这是#1 的变体。使用
synchronized(this)
是您界面的一部分。如果您不想/不需要暴露此内容,请不要这样做。