2012-06-23 4 views
6

可能性の重複:
Avoid synchronized(this) in Java?"this"またはJavaのプライベートオブジェクトでの同期化?

コードの2枚の違いは何ですか?それぞれのメリットとデメリットは何ですか?

1)

public class Example { 
private int value = 0; 

public int getNextValue() { 
    synchronized (this) { 
     return value++; 
    } 
} 
} 

2)

public class Example { 
private int value = 0; 

private final Object lock = new Object(); 

public int getNextValue() { 
    synchronized (lock) { 
     return value++; 
    } 
} 
} 
+2

言及したものを

そうでなければ第2のアプローチは、に基づいて、より良い仕事でしょう(私の知る限り) - しかし、なぜ? 「this」(外からの「オブジェクト」だけ)の可視性はどのような悪影響を及ぼしますか? 「悪いコード」がどのようにして同期ターゲットに干渉を引き起こす可能性がありますか? –

+0

'pubilc synchronized int getNextValue(){...}'は 'public int getNextValue(){synchronized(this){...}}'と全く同じですか? – Miquel

答えて

3

主な理由は、私は、クライアントが私のクラスのインスタンスで何をすべきかを制御できないということです。 I「は、私のExampleクラス内で、

class ClientCode { 
    Example exampleInstance; 

    void someMethod() { 
     synchronized (exampleInstance) { 
      //... 
     } 
    } 
} 

の場合:、何らかの理由で、誰かがロックとして私のクラスのインスタンスを使用することを決定した場合

、彼らは私のクラス内の同期ロジックを妨害します他の誰も見ることのできないロックを使用すると、上記のシナリオのように自分のロジックを妨げたり、任意のミューテックスを導入することはできません。

要約すると、これは情報隠蔽の原理の単なるアプリケーションです。

0

私は第二の方法が優れていると言うでしょう。次のような状況を考えてみます。このような状況this

public class Abc{ 

    private int someVariable; 

    public class Xyz { 
     //some method,synchronize on this 
    } 

     //some method, and again synchronize on this 


} 

は二つの方法では同じではありません。 1つは内部クラスのメソッドです。したがって、同期のために共通のオブジェクトを使用する方が良いです。例えば、synchronized (someVariable)

+0

しかし、 'synchronize(Abc.this) 'を使うことができます。 – Thilo

+0

はい。これもまた別の方法ですが、問題は 'this'です。すなわち、現在の' Object'の参照です。私は間違っているかもしれませんが、まだ初心者です。 :-) –

+1

Java Concurrency in Practiceにこのバグがありました。 –

3

2つの異なるタスクを互いに独立して同時に実行する必要がある場合は、2番目のオプションを優先します。私は2番目のアプローチを選択する理由

例えば:

public class Example { 
    private int value = 0; 
    private int new_value = 0; 
    private final Object lock1 = new Object(); 
    private final Object lock2 = new Object(); 

    public int getNextValue() { 
     synchronized (lock1) { 
      return value++; 
     } 
    } 

    public int getNextNewValue() { 
     synchronized (lock2) {    
      return new_value++; 
     } 
    } 
} 
0

本当に状況によると思います。あなたのクラスがサブクラスであり、スーパークラスが同期を持つメソッドを持っているとします。また、同じデータセットで作業しており、メソッド内で整合性を維持したいとします。そして、確実に1に近づくことがあなたが使用すべきものです。 Costiは、第二のアプローチはほとんど常により良いです

+0

私はあなたに同意しますが、この場合はスーパークラスが正しく設計されていないと言います。同期ロジック全体を公に利用できるようにすることなく、サブクラスで使用できる 'protected'ロックを提供することができます。 –

+1

@CostiCiudatuあなたには完全に同意します。これは、他の人のコードベースからいくつかのクラスを継承する場合にのみ発生します。おそらくこれはまれです。 – Vidyanand

+0

+1良質な皮肉のために - これはおそらくまれです。私のポイントは、あなたが選択できるときにはこのアプローチが*推奨されていないことを強調することでしたが、いくつかのシナリオでは唯一利用可能な方法です。 –

関連する問題