1. ホーム
  2. java

[解決済み] Javaでsynchronized(this)を避けるには?

2022-03-24 16:11:25

質問

SOでJavaの同期に関する質問が出ると、やたらと指摘する人がいる。 synchronized(this) は避けるべきでしょう。代わりに、プライベートな参照へのロックが望ましいと主張します。

与えられた理由のいくつかを紹介します。

私を含め、他の人たちは次のように主張しています。 synchronized(this) は、(Javaのライブラリでも)よく使われているイディオムで、安全であり、よく理解されています。バグがあるから、マルチスレッドプログラムで何が起こっているのかわからないから、という理由で避けるべきではありません。言い換えれば、適用できるのであれば、それを使いなさいということです。

へのロックを回避する実例を(foobarのようなものでなく)見てみたいと思っています。 this の方が望ましい。 synchronized(this) でもよい。

ですから。 は常に避けるべきでしょう。 synchronized(this) を使用し、プライベート参照へのロックに置き換えるか?


詳細情報(回答があり次第更新します。)

  • インスタンスの同期化について話しています
  • 暗黙的な( synchronized メソッド) と明示的な synchronized(this) とされています。
  • ブロッホや他の権威者を引用する場合、気に入らない部分を省かないこと(例:Effective Java、Thread Safetyの項目。 一般的にはインスタンス自体のロックですが、例外もあります)。
  • 以外のロックの粒度が必要な場合は、以下のようになります。 synchronized(this) が提供するのは synchronized(this) は適用されないので、それは問題ではない

解決方法は?

各ポイントを個別に説明します。

  1. 邪悪なコードがあなたのロックを盗むかもしれません(これは非常に人気があります。 偶然の産物)

    それよりも心配なのは うっかり . 何が言いたいかというと、この使い方は this は、あなたのクラスの公開されたインターフェイスの一部であり、文書化されるべきものです。 時には、他のコードがあなたのロックを使用できるようにすることが望まれます。 これは次のような場合に当てはまります。 Collections.synchronizedMap (javadocを参照)。

  2. <ブロッククオート

    同じクラス内のすべての同期化されたメソッドは、まったく同じ ロックされるため、スループットが低下する

    これはあまりにも単純な考え方で、単に synchronized(this) は解決しません。 スループットのために適切な同期をとるには、もっと熟考が必要です。

  3. あなたは(不必要に)多くの情報を暴露している

    1の変形版です。 使用方法 synchronized(this) は、あなたのインターフェースの一部です。 もし、これを公開したくない、または公開する必要がないのであれば、やらないことです。