54

同期方式と同期ブロックの違いはわかりますが、同期ブロック部分についてはよくわかりません。

私がこのコードを持っていると仮定して

class Test {
  private int x=0;
  private Object lockObject = new Object();

  public void incBlock() {
    synchronized(lockObject) {
      x++;
    }
    System.out.println("x="+x);
  }

  public void incThis() {  // same as synchronized method
    synchronized(this) {
      x++;
    }
    System.out.println("x="+x);
  }
}

この場合、 lockObjectを使用することとこれをロックとして使用することの違いは何ですか?それは私にも同じようです。

同期ブロックを使用する場合、どのオブジェクトをロックするかをどのように決定しますか?

4

5 に答える 5

66

個人的には、「これ」をロックすることはほとんどありません。私は通常、他のコードがロックオンしないことを知っている非公開の参照をロックします。「this」をロックすると、オブジェクトを認識している他のコードがロックを選択する可能性があります発生する可能性は低いですが、発生する可能性は確かにあります。デッドロックや過度のロックが発生する可能性があります。

あなたがロックするものについて特に魔法のようなものは何もありません-あなたはそれを事実上トークンとして考えることができます。同じトークンでロックしている人は誰でも同じロックを取得しようとします。他のコードが同じロックを取得できるようにする場合を除いて、プライベート変数を使用しますまた、変数を作成することをお勧めします。オブジェクトの存続期間中にロック変数を変更したいと思ったことfinalありません。

于 2010-07-30T07:04:15.163 に答える
13

Java Concurrency In Practiceを読んでいたときにも同じ質問があり、JonSkeetとspullaraから提供された回答にいくつかの視点を追加したいと思いました。

メソッドの実行中に「クイック」setValue(int)/getValue()メソッドもブロックするサンプルコードを次に示します。doStuff(ValueHolder)

public class ValueHolder {
    private int value = 0;

    public synchronized void setValue(int v) {
        // Or could use a sychronized(this) block...
        this.value = 0;
    }

    public synchronized int getValue() {
        return this.value;
    }
}

public class MaliciousClass {

    public void doStuff(ValueHolder holder) {
        synchronized(holder) {
            // Do something "expensive" so setter/getter calls are blocked
        }
    }
}

同期に使用することの欠点は、this他のクラスがクラスへの参照で同期できることです(thisもちろん、経由ではありません)。オブジェクトの参照をロックしているときにキーワードを悪意のある、または意図せずに使用すると、synchronized同時使用時にクラスの動作が低下する可能性があります。これは、外部クラスが同期されたthisメソッドを効果的にブロックする可能性があり、これを禁止するために(クラス内で)できることは何もないためです。実行時。この潜在的な落とし穴を回避するには、で同期するprivate final Objectか、のLockインターフェイスを使用しますjava.util.concurrent.locks

この簡単な例ではAtomicInteger、セッター/ゲッターを同期するのではなく、代わりに使用できます。

于 2010-08-02T01:45:14.640 に答える
5

効果的なJavaSecondEditionの項目67は、過度の同期を回避することです。したがって、プライベートロックオブジェクトで同期します。

于 2010-07-30T07:07:22.323 に答える
1

Javaのすべてのオブジェクトは、モニターとして機能できます。いずれかを選択するかどうかは、必要な粒度によって異なります。'this'を選択すると、他のクラスも同じモニターで同期できるという長所と短所があります。ただし、私のアドバイスは、synchronizeキーワードを直接使用することを避け、代わりに、より高レベルで明確に定義されたセマンティクスを持つjava.util.concurrencyライブラリの構成を使用することです。この本には、非常に著名な専門家からの素晴らしいアドバイスがたくさんあります。

実際のJava並行 性http://amzn.com/0321349601

于 2010-07-30T07:09:37.903 に答える
0

この場合、どのオブジェクトをロックに選択するかは重要ではありません。ただし、正しい同期を実現するには、ロックに同じオブジェクトを一貫して使用する必要があります。上記のコードでは、「this」オブジェクトをロックとして使用し、次に「lockObject」をロックとして使用するため、適切な同期が保証されません。

于 2010-07-30T07:05:00.110 に答える