回答:
静的メソッドには関連付けられたオブジェクトがないため、 同期されたキーワードはオブジェクトではなくクラスをロックしますか?
はい。:)
this
インスタンスメソッドでロックが取得されています- オスカーを修正してください。
オスカーの回答に少し詳細を追加するだけで(喜ばしいほど簡潔です!)、Java言語仕様の関連セクションは8.4.3.6の「同期メソッド」です。
同期されたメソッドは、実行する前にモニター(§17.1)を取得します。クラス(静的)メソッドの場合、メソッドのクラスのClassオブジェクトに関連付けられたモニターが使用されます。インスタンスメソッドの場合、これに関連付けられたモニター(メソッドが呼び出されたオブジェクト)が使用されます。
注意する必要がある1つの点(通常、いくつかのプログラマーはその罠に陥ります)は、同期された静的メソッドと同期された非静的メソッドの間にリンクがないということです。
class A {
static synchronized f() {...}
synchronized g() {...}
}
メイン:
A a = new A();
スレッド1:
A.f();
スレッド2:
a.g();
f()とg()は互いに同期していないため、完全に同時に実行できます。
synchronized (MyClass.class) {...}
。
次のようにg()を実装しない限り:
g() {
synchronized(getClass()) {
...
}
}
このパターンは、オブジェクトの異なるインスタンス間で相互排他を実装する場合にも役立ちます(たとえば、外部リソースにアクセスするときに必要です)。
getClass()
返すことを忘れないでください。クラスをサブクラス化すると、親クラスと子クラスは異なるロックで同期します。すべてのインスタンスが同じロックを使用することを確認する必要がある場合の方法です。synchronized(MyClass.class)
本質的なロックと同期に関するオラクルのドキュメントページをご覧ください。
静的メソッドはオブジェクトではなくクラスに関連付けられているため、静的同期メソッドが呼び出されたときに何が起こるか疑問に思うかもしれません。この場合、スレッドは、classに関連付けられたClassオブジェクトの固有のロックを取得します。したがって、クラスの静的フィールドへのアクセスは、クラスのインスタンスのロックとは異なるロックによって制御されます。
静的メソッドには、関連するオブジェクトもあります。JDKツールキットのClass.classファイルに属しています。.classファイルがRAMにロードされると、Class.classはテンプレートオブジェクトと呼ばれるそのインスタンスを作成します。
例:-既存の顧客クラスからオブジェクトを作成しようとした場合
Customer c = new Customer();
Customer.classがRAMにロードされます。その瞬間、JDKツールキットのClass.classは、テンプレートオブジェクトと呼ばれるオブジェクトを作成し、そのCustomer.classをそのテンプレートオブジェクトにロードします。そのCustomer.classの静的メンバーは、そのテンプレートオブジェクトの属性とメソッドになります。
したがって、静的メソッドまたは属性にもオブジェクトがあります
以下の例は、クラスとオブジェクトのロックをより明確にします。以下の例が他の人にも役立つことを願っています:)
たとえば、以下のメソッドには、1つの取得クラスと他の取得オブジェクトロックがあります。
public class MultiThread {
public static synchronized void staticLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
public synchronized void objLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
したがって、次のシナリオが可能になります。
同じオブジェクトを使用するスレッドがobjLock
OR staticLock
メソッドに同時にアクセスしようとした場合(つまり、両方のスレッドが同じメソッドにアクセスしようとした場合)
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
同じオブジェクトを使用するスレッドが同時にメソッドstaticLock
とobjLock
メソッドにアクセスしようとしたとき(異なるメソッドへのアクセスを試行)
Thread-0 0
Thread-1 0
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 2
Thread-1 3
Thread-0 3
Thread-0 4
Thread-1 4
異なるオブジェクトを使用するスレッドがstaticLock
メソッドにアクセスしようとしたとき
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
異なるオブジェクトを使用するスレッドがobjLock
メソッドにアクセスしようとしたとき
Thread-0 0
Thread-1 0
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 2
Thread-1 3
Thread-0 3
Thread-0 4
Thread-1 4