synchronized(Foo.Class){
//some code..
}
これは Foo クラスのすべてのインスタンスをロックしますか、それとも静的メソッド/フィールドのみをロックしますか?
synchronized(Foo.Class){
//some code..
}
これは Foo クラスのすべてのインスタンスをロックしますか、それとも静的メソッド/フィールドのみをロックしますか?
クラス オブジェクトの同期は、インスタンスの同期とまったく同じように機能します。などのクラスFoo.class
はオブジェクトであるため、組み込みのモニターがあります。あなたが提供したコード:
synchronized(Foo.Class){
//some code..
}
Foo クラスへのアクセスを同期します。クラスの静的変数を同期しようとするときに役立ちます。例えば:
public class Foo{
private static int COUNTER = 0;
synchronized public static void increment(){
COUNTER ++;
}
public static void decrement(){
synchronized (Foo.class) {
COUNTER ++;
}
}
}
ご覧のとおり、同期はFoo.class
他のインスタンスと同じように実現できます。インスタンスのコード ブロックを同期しようとすると、クラス オブジェクトの場合synchronized(this){}
と同等の : が使用されます。synchronized(Foo.class){}
同期されたメソッドの場合も同じことが当てはまります: synchronized public void increment(){}
は以下と同等です:synchronized public static void increment(){}
今あなたの質問に関して:
これは Foo クラスのすべてのインスタンスをロックしますか、それとも静的メソッド/フィールドのみをロックしますか?
もちろん、上記で説明したように、すべてのインスタンスのロックを取得するわけではありません。さらに、クラス オブジェクトは作成されたインスタンスを認識しません。synchronized
ブロックはフィールドをロックしません。ロックを取得したスレッドによってアトミック操作として強制的に実行されるコード/メソッドのブロックのみをロックし、他のスレッドはそのコード ブロックに入ることができません (ただし、同期されていない場合は他のブロックを実行できます)。最初のスレッドがロックを解放します (Java では中かっこの終わりです}
)。
それを使用するメソッド/同期句へのアクセスを同期します。これらはクラス Bar のメソッドである可能性があります -- Foo である必要はありません。
重要なことは、「Foo.class」で同期するすべてのメソッド/同期句が、同時に実行されることから相互に除外されることです。
同期はフィールドにはまったく影響しません。同期されたフィールドを宣言する方法はありません。
チュートリアル の私の解釈ではsynchronized(Foo.class) {...}
、クラスの静的メンバーのみがロックされます。しかし、確実にするには、テストを書く必要があります。
public class SyncTest {
public static SyncTest instance;
public static String valueA;
public String valueB;
public static void main(String[] args) {
instance = new SyncTest();
(new Thread(new Task1())).start();
(new Thread(new Task2())).start();
try {
Thread.sleep(10000);
synchronized(SyncTest.class) {
System.out.println("Value A: " + valueA);
}
synchronized(instance) {
System.out.println("Value B: " + instance.valueB);
}
} catch (InterruptedException interrupt) { }
}
}
class Task1 implements Runnable {
public void run() {
try {
synchronized(SyncTest.class) {
System.out.println("Task 1 Sleeping ");
Thread.sleep(500);
SyncTest.valueA = "One";
System.out.println("T1 A: " + SyncTest.valueA);
}
synchronized(SyncTest.instance) {
Thread.sleep(1000);
SyncTest.instance.valueB = "Two";
System.out.println("T1 B: " + SyncTest.instance.valueB);
}
} catch (InterruptedException interrupt) { }
System.out.println("Task 1 Finished ");
}
}
class Task2 implements Runnable {
public void run() {
System.out.println("Task 2 Started");
try {
Thread.sleep(1000);
synchronized(SyncTest.class) {
SyncTest.instance.valueB = "Four";
System.out.println("T2 B: " + SyncTest.instance.valueB);
Thread.sleep(5000);
SyncTest.valueA = "Three";
System.out.println("T2 A: " + SyncTest.valueA);
}
} catch (InterruptedException interrupt) { }
System.out.println("Task 2 Finished");
}
}
出力は次のとおりです。
Task 1 Sleeping
Task 2 Started
T1 A: One
T2 B: Four
T1 B: Two
Task 1 Finished
T2 A: Three
Task 2 Finished
Value A: Three
Value B: Two
タスク 1 がインスタンス ロックを保持している間にタスク 2 が更新valueB
されるため、これは静的ロックがクラスのすべてのインスタンスをロックしていないことを示していると思います。