Im Beispiel sind Methode A und Methode B Instanzmethoden (im Gegensatz zu statischen Methoden). Puttensynchronized
einer Instanzmethode bedeutet, dass der Thread die Sperre (die "intrinsische Sperre") für die Objektinstanz erwerben muss, für die die Methode aufgerufen wird, bevor der Thread mit der Ausführung von Code in dieser Methode beginnen kann.
Wenn zwei verschiedene Instanzmethoden als synchronisiert markiert sind und verschiedene Threads diese Methoden gleichzeitig für dasselbe Objekt aufrufen, kämpfen diese Threads um dieselbe Sperre. Sobald ein Thread die Sperre erhält, werden alle anderen Threads von allen synchronisierten Instanzmethoden für dieses Objekt ausgeschlossen.
Damit die beiden Methoden gleichzeitig ausgeführt werden können, müssten sie unterschiedliche Sperren verwenden:
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
}
}
}
Dabei ermöglicht die synchronisierte Blocksyntax die Angabe eines bestimmten Objekts, für das der ausführende Thread die intrinsische Sperre erhalten muss, um in den Block einzutreten.
Es ist wichtig zu verstehen, dass, obwohl wir einzelne Methoden mit einem "synchronisierten" Schlüsselwort versehen, das Kernkonzept die intrinsische Sperre hinter den Kulissen ist.
So beschreibt das Java-Tutorial die Beziehung:
Die Synchronisierung basiert auf einer internen Entität, die als intrinsische Sperre oder Monitorsperre bezeichnet wird. (In der API-Spezifikation wird diese Entität häufig einfach als "Monitor" bezeichnet.) Intrinsische Sperren spielen bei beiden Aspekten der Synchronisation eine Rolle: Erzwingen des exklusiven Zugriffs auf den Status eines Objekts und Herstellen von Vor-Vor-Beziehungen, die für die Sichtbarkeit wesentlich sind.
Jedem Objekt ist eine intrinsische Sperre zugeordnet. Gemäß der Konvention muss ein Thread, der exklusiven und konsistenten Zugriff auf die Felder eines Objekts benötigt, die intrinsische Sperre des Objekts abrufen, bevor er auf sie zugreift, und dann die intrinsische Sperre aufheben, wenn sie mit ihnen abgeschlossen ist. Ein Thread soll die intrinsische Sperre zwischen dem Zeitpunkt, zu dem er die Sperre erworben und die Sperre aufgehoben hat, besitzen. Solange ein Thread eine intrinsische Sperre besitzt, kann kein anderer Thread dieselbe Sperre erhalten. Der andere Thread wird blockiert, wenn er versucht, die Sperre zu erlangen.
Der Zweck des Sperren besteht darin, gemeinsam genutzte Daten zu schützen. Sie würden separate Sperren verwenden, wie im obigen Beispielcode gezeigt, nur wenn jede Sperre unterschiedliche Datenelemente schützt.