同期を視覚化して理解しようとしています。
コードA
public class MyClass1 {
private static final Object lock = new Object();
public MyClass1() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
コードB
public class MyClass2 {
private final Object lock = new Object();
public MyClass2() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
注
上記のコードはコンストラクターを示していますが、静的メソッドと非静的メソッドでの動作の違いについても説明できます。また、同期ブロックが静的メンバー変数を変更しているときに静的ロックを使用すると有利ですか?
私はすでに この質問 で答えを見ましたが、異なる使用シナリオが何であるかは十分に明確ではありません。
違いは簡単です。ロックされたオブジェクトがstatic
フィールドにある場合、_MyClass*
_のすべてのインスタンスは共有そのロック(つまり、2つのオブジェクトは使用できません)そのオブジェクトを同時にロックします)。
フィールドが非静的の場合、各インスタンスは独自のロックを持つため、メソッド(同じオブジェクト上)の呼び出しのみが相互にロックします。
静的ロックオブジェクトを使用する場合:
o1.foo()
を呼び出しますo1.foo()
を呼び出し、スレッド1が終了するまで待機する必要がありますo2.foo()
を呼び出し、alsoスレッド1(そしておそらく2)が終了するのを待たなければなりません非静的ロックオブジェクトを使用する場合:
o1.foo()
を呼び出しますo1.foo()
を呼び出し、スレッド1が終了するまで待機する必要がありますo2.foo()
を呼び出します。スレッド1と2を気にせずに続行できますどれが必要なのかは、同期ブロックでprotectを試みるデータの種類によって異なります。
経験則として、ロックオブジェクトには、操作対象の値と同じstatic
- nessが必要です。したがって、非静的な値onlyを操作する場合、非静的なロックオブジェクトが必要になります。静的な値onlyを操作する場合、静的ロックオブジェクトが必要になります。
静的および非静的値を操作すると、複雑になります。 easyの方法は、静的ロックオブジェクトを使用することですが、これにより、同期ブロックのサイズが絶対的に必要以上に大きくなり、必要以上にロック競合が必要になる場合があります。そのような場合、静的ロックオブジェクトと非静的ロックオブジェクトの組み合わせが必要になる場合があります。
特定のケースでは、コンストラクターでロックを使用します。これはインスタンスごとに1回だけ実行されるため、ここでは非静的ロックオブジェクトは意味をなしません。