Java同期静的メソッド:オブジェクトまたはクラスのロック
-
22-07-2019 - |
質問
Javaチュートリアルでは、「同じオブジェクトで同期メソッドを2回呼び出してインターリーブすることはできません」とあります。
これは静的メソッドにとって何を意味しますか?静的メソッドにはオブジェクトが関連付けられていないため、同期キーワードはオブジェクトではなくクラスをロックしますか?
解決
静的メソッドにはオブジェクトが関連付けられていないため、同期キーワードはオブジェクトではなくクラスをロックしますか?
はい。 :)
他のヒント
オスカーの(簡単に!)答えに少し詳細を追加するだけで、Java言語仕様の関連セクションは 8.4.3.6、「同期メソッド」:
同期メソッドは、実行前にモニター(§ 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()) {
...
}
}
このパターンは、オブジェクトの異なるインスタンス間で相互排他を実装する場合にも役立ちます(たとえば、外部リソースにアクセスするときに必要です)。
固有のロックと同期のオラクルドキュメントページをご覧ください。 a>
静的メソッドはオブジェクトではなくクラスに関連付けられているため、静的同期メソッドが呼び出されるとどうなるのかと疑問に思われるかもしれません。 この場合、スレッドはクラスに関連付けられたClassオブジェクトの固有のロックを取得します。 したがって、クラスの静的フィールドへのアクセスは、クラスのインスタンスのロックとは異なるロックによって制御されます。。
静的メソッドには、関連付けられたオブジェクトもあります。 JDKツールキットのClass.classファイルに属します。 .classファイルがRAMにロードされると、Class.classはテンプレートオブジェクトと呼ばれるそのインスタンスを作成します。
例:-既存の顧客クラスからオブジェクトを作成しようとするとき
Customer c = new Customer();
Customer.classがRAMにロードされます。その瞬間、JDKツールキットのClass.classはTemplateオブジェクトと呼ばれるオブジェクトを作成し、その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
または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
メソッドにアクセスしようとしたとき -
異なるオブジェクトを使用するスレッドが
<*>objLock
メソッドにアクセスしようとしたとき
クラスオブジェクトでロックされた静的な同期メソッドに慣れていない人向け文字列クラスの場合はString.class、インスタンス同期メソッドはJavaの「this」キーワードで示されるオブジェクトの現在のインスタンスをロックします。これらのオブジェクトは両方とも異なるため、1つのスレッドが静的同期メソッドを実行している間、ロックが異なるため、javaの他のスレッドは、そのスレッドが戻るのを待つ必要がなく、代わりにbyte .classリテラルで示される別のロックを取得して入力します静的同期メソッド。