Javaチュートリアルには、「同じオブジェクトで同期化されたメソッドを2回呼び出すことでインターリーブすることはできません」とあります。
これは静的メソッドにとって何を意味しますか?静的メソッドにはオブジェクトが関連付けられていないため、同期キーワードはオブジェクトではなくクラスをロックしますか?
静的メソッドには関連付けられたオブジェクトがないため、同期キーワードはオブジェクトではなくクラスをロックしますか?
はい。 :)
オスカーの(簡単に!)答えに少し詳細を追加するために、Java言語仕様の関連セクションは 8.4.3.6、 'synchronized Methods' です。
同期メソッドは、実行前にモニター(§17.1)を取得します。クラス(静的)メソッドの場合、メソッドのクラスのClassオブジェクトに関連付けられたモニターが使用されます。インスタンスメソッドの場合、これに関連付けられたモニター(メソッドが呼び出されたオブジェクト)が使用されます。
注意しなければならない点の1つは(いくつかのプログラマーは一般にそのtrapに陥ります)、同期された静的メソッドと同期された非静的メソッドの間にリンクがないことです。
class A {
static synchronized f() {...}
synchronized g() {...}
}
メイン:
A a = new A();
スレッド1:
A.f();
スレッド2:
a.g();
f()とg()は互いに同期していないため、完全に同時に実行できます。
次のようにg()を実装しない限り:
g() {
synchronized(getClass()) {
...
}
}
このパターンは、オブジェクトの異なるインスタンス間で相互排他を実装する場合にも役立ちます(たとえば、外部リソースにアクセスするときに必要です)。
Intrinsic Locks and Synchronization のOracleドキュメントページをご覧ください。
静的メソッドはオブジェクトではなくクラスに関連付けられているため、静的同期メソッドが呼び出されるとどうなるのかと疑問に思われるかもしれません。 この場合、スレッドは、クラスに関連付けられた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
または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
静的メソッドにもオブジェクトが関連付けられています。 JDKツールキットのClass.classファイルに属します。 .classファイルがRAMにロードされると、Class.classはテンプレートオブジェクトと呼ばれるそのインスタンスを作成します。
例:-のような既存の顧客クラスからオブジェクトを作成しようとするとき
Customer c = new Customer();
Customer.classがRAMにロードされます。その瞬間、JDKツールキットのClass.classはTemplateオブジェクトと呼ばれるオブジェクトを作成し、そのCustomer.classをそのテンプレートオブジェクトにロードします。そのCustomer.classの静的メンバーは、そのテンプレートオブジェクトの属性とメソッドになります。
そのため、静的メソッドまたは静的属性にもオブジェクトがあります
クラスオブジェクトでロックされている静的同期メソッドに慣れていない人向け文字列クラスの場合はString.classで、インスタンス同期メソッドはJavaの「this」キーワードで示されるオブジェクトの現在のインスタンスをロックします。これらのオブジェクトは両方とも異なるロックを持っているため、1つのスレッドが静的同期メソッドを実行している間、Javaの他のスレッドは、そのスレッドが戻るのを待つ必要がなく、バイトで示される個別のロックを取得します.classリテラルおよび静的同期メソッドに入ります。