この例では、methodA と methodB はインスタンス メソッドです (静的メソッドではありません)。インスタンスsynchronized
メソッドを使用するということは、スレッドがそのメソッド内のコードの実行を開始する前に、メソッドが呼び出されるオブジェクト インスタンスのロック (「組み込みロック」) をスレッドが取得する必要があることを意味します。
同期とマークされた 2 つの異なるインスタンス メソッドがあり、異なるスレッドが同じオブジェクトでこれらのメソッドを同時に呼び出している場合、それらのスレッドは同じロックを求めて競合します。1 つのスレッドがロックを取得すると、他のすべてのスレッドは、そのオブジェクトの同期されたすべてのインスタンス メソッドから締め出されます。
2 つのメソッドを同時に実行するには、次のように異なるロックを使用する必要があります。
class A {
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized(lockA) {
//method A
}
}
public void methodB() {
synchronized(lockB) {
//method B
}
}
}
ここで、同期ブロック構文を使用すると、実行中のスレッドがブロックに入るために固有のロックを取得する必要がある特定のオブジェクトを指定できます。
理解しておくべき重要なことは、個々のメソッドに「同期」キーワードを置いているにもかかわらず、中心的な概念は舞台裏の本質的なロックであることです。
Java チュートリアルでの関係の説明は次のとおりです。
同期は、固有ロックまたはモニター ロックと呼ばれる内部エンティティを中心に構築されます。(API 仕様では、このエンティティを単に「モニター」と呼ぶことがよくあります。) 組み込みロックは、同期の両方の側面で役割を果たします。つまり、オブジェクトの状態への排他的アクセスを強制し、可視性に不可欠な事前発生関係を確立します。
すべてのオブジェクトには固有のロックが関連付けられています。慣例により、オブジェクトのフィールドへの排他的かつ一貫したアクセスを必要とするスレッドは、オブジェクトにアクセスする前にオブジェクトの固有ロックを取得し、それらの操作が完了したら固有ロックを解放する必要があります。スレッドは、ロックを取得してからロックを解放するまでの間、固有のロックを所有していると見なされます。スレッドが固有ロックを所有している限り、他のスレッドが同じロックを取得することはできません。他のスレッドは、ロックを取得しようとするとブロックされます。
ロックの目的は、共有データを保護することです。各ロックが異なるデータ メンバーを保護する場合にのみ、上記のコード例に示すように個別のロックを使用します。