2012-01-29 7 views
12

various reasonsの場合、synchronized(this)は避けるべきです。しかし、私が遭遇したいくつかの立派なコードは、コンストラクタに次のように使用します。synchronized(this)とsynchronized(ClassName.class)の違いは何ですか?

public SomeClass(Context context) { 
    if (double_checked_lock == null) { 
    synchronized (SomeClass.class) { 
     if (double_checked_lock == null) { 
     // some code here 
     } 
    } 
    } 
} 

は本当にsynchronized(this)synchronized(SomeClass.class)の違いはありますか?

答えて

23

synchronized(this)は現在のオブジェクトで同期されているため、1つのスレッドだけが各インスタンスにアクセスできますが、異なるスレッドは異なるインスタンスにアクセスできます。例えば。スレッドごとに1つのインスタンスを持つことができます。

これは、複数のスレッドが同時にオブジェクトを更新して矛盾した状態になるのを防ぐのに便利です。 (一方は希望場合、または別のクラス)

synchronized(SomeClass.class)は、現在のオブジェクトのクラスに同期されるので、一度に一つのスレッドは、そのクラスの任意インスタンスにアクセスすることができます。

これは、クラスのすべてのインスタンス(おそらくはインスタンスキャッシュ)間で共有されるデータが矛盾した状態になるのを防ぐために使用されます。

+1

+1。これにより、クラスロックとオブジェクトロックがより明確になります。私はこれ以上何も見つけられませんでした。 *短いと理解しやすい* – Ravi

5

は、インスタンスごとに異なります。
ClassName.classではありません。

したがって、synchronized(this)は、複数のインスタンスを同時に実行できるようにします。

3

​​キーワードは、クラスのロックをclassに適用すると、現在のオブジェクトインスタンスのロックをthisに適用したときに適用されます。 Java言語仕様のセクション8.4.3.6, 'synchronized Methods'

同期メソッドは、実行する前にモニター(17.1)を取得します。クラス(静的)メソッドの場合、メソッドのクラスのClassオブジェクトに関連付けられたモニターが使用されます。インスタンスメソッドの場合、これに関連付けられたモニター(メソッドが呼び出されたオブジェクト)が使用されます。

1

これらにロックする2つの異なる目的である: 「これは」は、例えば、各スレッドは、その上に別のインスタンスとロックを使用し、もしそうであれば、複数のインスタンスを作成することは効果がないであろう、現在のインスタンスのコンテキストを指します。 'this'は非静的コンテキストでのみ参照できます。
'class'はJavaクラスの静的メンバーであり、正確に1つのインスタンスがあります。静的コンテキストと非静的コンテキストの両方でロックできます。

1

synchronized(this)は、オブジェクトのインスタンスに同期します。

synchronized(SomeClass.class)は、同じクラスローダー内のすべてのインスタンスに対してグローバルであるSomeClassを表すClassオブジェクトのインスタンスを使用します。

したがって、これらは異なるセマンティクスを持つ異なる構文です。

​​を単独で使用するか、メソッド修飾子として使用すると、そのインスタンスを共有リソース(つまりリスト)としてアクセスする複数のスレッド間の競合を防ぐために通常使用されるインスタンスのセマフォにも同期します。

あなたが参照しているスレッドは、あなたのオブジェクトインスタンスに直接同期することは危険である可能性があるため、プライベートインスタンスを使用する方が良い方法だと述べています。そのためには:

class MySharedResourceClass { 

    private SomeClass lock = new SomeClass(); 

    public doSomething() { 
     synchronized (lock) { 
      // Do something here 
     } 
    } 
} 
2

それぞれのJavaオブジェクトはロックを持つことができます。このロックは、一度に最大でも1つのスレッドによって保持され、同じオブジェクトのロックを取得するために他のスレッドが待機する必要があります。

  • synchronized(this)現在のスレッドのインスタンスthisのロックを取得します。このメソッドは異なるインスタンスで異なるパラレルで実行できます(異なるロック、異なるロックのため異なる値)

  • synchronized(SomeClass.class)はSomeClassのグローバルクラスオブジェクトのロックを取得します。すべてのオブジェクトインスタンスが同じグローバルオブジェクト(同じロック)でロックされるため、メソッドのインスタンスは1つしか実行できません。

関連する問題