在 Java 中避免同步(这个)? [英] Avoid synchronized(this) in Java?

查看:26
本文介绍了在 Java 中避免同步(这个)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每当 SO 上出现关于 Java 同步的问题时,有些人非常渴望指出应该避免 synchronized(this).相反,他们声称,最好锁定私有引用.

Whenever a question pops up on SO about Java synchronization, some people are very eager to point out that synchronized(this) should be avoided. Instead, they claim, a lock on a private reference is to be preferred.

给出的一些原因是:

  • some evil code may steal your lock (very popular this one, also has an "accidentally" variant)
  • all synchronized methods within the same class use the exact same lock, which reduces throughput
  • you are (unnecessarily) exposing too much information

其他人,包括我,认为 synchronized(this) 是一个经常使用的习语(也在 Java 库中),是安全且易于理解的.它不应该被避免,因为您有一个错误并且您不知道您的多线程程序中发生了什么.换句话说:如果它适用,那就使用它.

Other people, including me, argue that synchronized(this) is an idiom that is used a lot (also in Java libraries), is safe and well understood. It should not be avoided because you have a bug and you don't have a clue of what is going on in your multithreaded program. In other words: if it is applicable, then use it.

我有兴趣看到一些现实世界的例子(没有 foobar 的东西),当 synchronized(this) 也可以完成这项工作时,最好避免锁定 this.

I am interested in seeing some real-world examples (no foobar stuff) where avoiding a lock on this is preferable when synchronized(this) would also do the job.

因此:您是否应该始终避免使用 synchronized(this) 并将其替换为对私有引用的锁定?

Therefore: should you always avoid synchronized(this) and replace it with a lock on a private reference?

一些进一步的信息(在给出答案时更新):

Some further info (updated as answers are given):

  • 我们正在谈论实例同步
  • 同时考虑了 synchronized(this) 的隐式(synchronized 方法)和显式形式
  • 如果你引用 Bloch 或其他权威人士的话说,不要遗漏你不喜欢的部分(例如 Effective Java,线程安全项目:通常是实例本身的锁,但是也有例外.)
  • 如果您需要除 synchronized(this) 以外的锁定粒度,则 synchronized(this) 不适用,所以这不是问题
  • we are talking about instance synchronization
  • both implicit (synchronized methods) and explicit form of synchronized(this) are considered
  • if you quote Bloch or other authorities on the subject, don't leave out the parts you don't like (e.g. Effective Java, item on Thread Safety: Typically it is the lock on the instance itself, but there are exceptions.)
  • if you need granularity in your locking other than synchronized(this) provides, then synchronized(this) is not applicable so that's not the issue

推荐答案

我将分别介绍每一点.

一些邪恶的代码可能会偷你的锁(这个很流行,还有一个意外"变体)

Some evil code may steal your lock (very popular this one, also has an "accidentally" variant)

我更担心意外.它的意思是 this 的这种使用是您的类公开接口的一部分,应该记录下来.有时需要其他代码使用您的锁的能力.Collections.synchronizedMap 之类的东西也是如此(请参阅 javadoc).

I'm more worried about accidentally. What it amounts to is that this use of this is part of your class' exposed interface, and should be documented. Sometimes the ability of other code to use your lock is desired. This is true of things like Collections.synchronizedMap (see the javadoc).

同一类中的所有同步方法都使用完全相同的锁,降低吞吐量

All synchronized methods within the same class use the exact same lock, which reduces throughput

这是过于简单化的想法;仅仅去掉 synchronized(this) 并不能解决问题.吞吐量的适当同步需要更多考虑.

This is overly simplistic thinking; just getting rid of synchronized(this) won't solve the problem. Proper synchronization for throughput will take more thought.

你(不必要地)暴露了太多信息

You are (unnecessarily) exposing too much information

这是#1 的变体.synchronized(this) 的使用是界面的一部分.如果你不想/不需要暴露这个,就不要这样做.

This is a variant of #1. Use of synchronized(this) is part of your interface. If you don't want/need this exposed, don't do it.

这篇关于在 Java 中避免同步(这个)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆