Kommt es zu Konflikten zwischen Klassensperren und Objektsperren? Kommt es zu Konflikten zwischen Objektsperren und privaten Sperren? Veranschaulichung durch Beispiele.
1. Relevante Vereinbarungen
Um die folgende Beschreibung zu verdeutlichen, treffen wir zunächst die folgenden Konventionen zu den relevanten Definitionen von Sperren, die in diesem Artikel behandelt werden:
1. Klassensperre: Fügen Sie den Methoden im Code statische und synchronisierte Sperren oder synchronisierte (xxx.class) Codesegmente hinzu, wie z. B. increament() unten;
2. Objektsperre: Fügen Sie der Methode im Code eine synchronisierte Sperre oder ein synchronisiertes (dieses) Codesegment hinzu, wie z. B. synOnMethod() und synInMethod() unten;
3. Private Sperre: Deklarieren Sie eine private Eigenschaft wie die private Objektsperre innerhalb der Klasse und synchronisieren (sperren) Sie das Codesegment, das gesperrt werden muss, wie z. B. synMethodWithObj() unten.
2. Testcode
1. Schreiben Sie eine Startup-Klasse ObjectLock
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse ObjectLock {
public static void main(String[] args) {
System.out.println("start time = " + System.currentTimeMillis()+"ms");
LockTestClass test = new LockTestClass();
for (int i = 0; i < 3; i++) {
Thread thread = new ObjThread(test, i);
thread.start();
}
}
}
2. Schreiben Sie eine Thread-Klasse ObjThread, um die Synchronisationsmethode zu starten (beachten Sie, dass die Ausführungsmethode für verschiedene Tests angepasst werden kann).
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse ObjThread erweitert Thread {
LockTestClass-Sperre;
int i = 0;
public ObjThread(LockTestClass lock, int i) {
this.lock = lock;
this.i = i;
}
public void run() {
//Lockless-Methode
//lock.noSynMethod(this.getId(),this);
//Objektsperrmethode 1 mit synchronisierter synInMethod
lock.synInMethod();
// Objektsperrmethode 2, Verwendung der synchronisierten (diesen) Methode
//lock.synOnMethod();
//Private Sperrmethode unter Verwendung der synchronisierten (Objekt-)Methode
//lock.synMethodWithObj();
//Klassensperrmethode unter Verwendung der statischen synchronisierten Inkrementmethode
LockTestClass.increment();
}
}
3. Schreiben Sie eine weitere Sperrtestklasse LockTestClass, einschließlich verschiedener Sperrmethoden
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse LockTestClass {
//Wird für die Klassensperrenzählung verwendet
privates statisches int i = 0;
//Private Sperre
privates Objekt object = new Object();
/**
* <p>
* Sperrfreie Methode
*
* @param ThreadID
* @param-Thread
*/
public void noSynMethod(long threadID, ObjThread thread) {
System.out.println("nosyn: class obj ist " + thread + ", threadId ist"
+ ThreadID);
}
/**
* Objektsperrmethode 1
*/
öffentlich synchronisiert void synOnMethod() {
System.out.println("synOnMethod beginnt" + ", time = "
+ System.currentTimeMillis() + "ms");
versuchen {
Thread.sleep(2000L);
} Catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synOnMethod endet");
}
/**
* Objektsperrmethode 2, verwenden Sie synchronisiert (dies) zum Sperren
*/
public void synInMethod() {
synchronisiert (dies) {
System.out.println("synInMethod beginnt" + ", time = "
+ System.currentTimeMillis() + "ms");
versuchen {
Thread.sleep(2000L);
} Catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synInMethod endet");
}
}
/**
* Objektsperrmethode 3
*/
public void synMethodWithObj() {
synchronisiert (Objekt) {
System.out.println("synMethodWithObj beginnt" + ", time = "
+ System.currentTimeMillis() + "ms");
versuchen {
Thread.sleep(2000L);
} Catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synMethodWithObj endet");
}
}
/**
* Klassensperre
*/
öffentliches statisches synchronisiertes void increament() {
System.out.println("class synchronisiert. i = " + i + ", time = "
+ System.currentTimeMillis() + "ms");
i++;
versuchen {
Thread.sleep(2000L);
} Catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("class synchronisiert endet.");
}
}
3. Testergebnisse
1. Um Klassensperren und Objektsperren zu testen, ändern Sie die Ausführungsmethode von ObjectThread wie folgt:
Kopieren Sie den Codecode wie folgt:
public void run() {
//Lockless-Methode
//lock.noSynMethod(this.getId(),this);
//Objektsperrmethode 1 mit synchronisierter synInMethod
lock.synInMethod();
// Objektsperrmethode 2, Verwendung der synchronisierten (diesen) Methode
//lock.synOnMethod();
//Private Sperrmethode unter Verwendung der synchronisierten (Objekt-)Methode
//lock.synMethodWithObj();
//Klassensperrmethode unter Verwendung der statischen synchronisierten Inkrementmethode
LockTestClass.increament();
}
Terminalausgabe:
Kopieren Sie den Codecode wie folgt:
Startzeit = 1413101360231 ms
synInMethod beginnt, Zeit = 1413101360233 ms
synInMethod endet
Klasse synchronisiert. i = 0, Zeit = 1413101362233ms
synInMethod beginnt, Zeit = 1413101362233 ms
Die synchronisierte Klasse endet.
synInMethod endet
Klasse synchronisiert. i = 1, Zeit = 1413101364233ms
synInMethod beginnt, Zeit = 1413101364233 ms
Die synchronisierte Klasse endet.
synInMethod endet
Klasse synchronisiert. i = 2, Zeit = 1413101366234ms
Klasse synchronisiert endet.
Sie können sehen, dass die Objektsperrmethode (synInMothod) beim ersten Start 2 Sekunden schneller ist als die Klassensperrmethode (Inkrementierung). Dies liegt daran, dass synInMehtod bei der Ausführung 2 Sekunden lang schläft und dann die Inkrementierung ausführt Methoden teilen sich denselben Thread. Wenn inkrementiert vor synInMethod platziert wird, erfolgt die Inkrementierung beim ersten Start um 2 Sekunden.
Wenn die Klassensperrmethode gestartet wird, wird fast gleichzeitig auch die Objektsperrmethode eines anderen Threads gestartet, was darauf hinweist, dass die beiden nicht dieselbe Sperre verwenden und keine Konkurrenz besteht.
Fazit: Klassensperren und Objektsperren konkurrieren nicht und ihre Sperrmethoden wirken sich nicht gegenseitig aus.
2. Private Sperren und Objektsperren. Die Ausführungsmethode von ObjectThread wird wie folgt geändert:
Kopieren Sie den Codecode wie folgt:
public void run() {
//Lockless-Methode
//lock.noSynMethod(this.getId(),this);
//Objektsperrmethode 1 mit synchronisierter synInMethod
lock.synInMethod();
// Objektsperrmethode 2, Verwendung der synchronisierten (diesen) Methode
//lock.synOnMethod();
//Private Sperrmethode unter Verwendung der synchronisierten (Objekt-)Methode
lock.synMethodWithObj();
//Klassensperrmethode unter Verwendung der statischen synchronisierten Inkrementmethode
//LockTestClass.increament();
}
Terminalausgabe:
Kopieren Sie den Codecode wie folgt:
Startzeit = 1413121912406 ms
synInMethod beginnt, Zeit = 1413121912407 ms.
synInMethod endet.
synMethodWithObj beginnt, Zeit = 1413121914407 ms
synInMethod beginnt, Zeit = 1413121914407 ms.
synInMethod endet.
synMethodWithObj endet
synInMethod beginnt, Zeit = 1413121916407 ms.
synMethodWithObj beginnt, Zeit = 1413121916407 ms
synInMethod endet.
synMethodWithObj endet
synMethodWithObj beginnt, Zeit = 1413121918407 ms
synMethodWithObj endet
Sehr ähnlich zu Klassensperren und Objektsperren.
Fazit: Private Sperren und Objektsperren konkurrieren nicht und ihre Sperrmethoden beeinflussen sich nicht gegenseitig.
3.Synchronized wird direkt zur Methode hinzugefügt und synchronisiert (dies), und die Ausführungsmethode von ObjectThread wird wie folgt geändert:
Kopieren Sie den Codecode wie folgt:
public void run() {
//Lockless-Methode
//lock.noSynMethod(this.getId(),this);
//Objektsperrmethode 1 mit synchronisierter synInMethod
lock.synInMethod();
// Objektsperrmethode 2, Verwendung der synchronisierten (diesen) Methode
lock.synOnMethod();
//Private Sperrmethode unter Verwendung der synchronisierten (Objekt-)Methode
//lock.synMethodWithObj();
//Klassensperrmethode unter Verwendung der statischen synchronisierten Inkrementmethode
//LockTestClass.increament();
}
Terminalausgabe:
Kopieren Sie den Codecode wie folgt:
Startzeit = 1413102913278 ms
synInMethod beginnt, Zeit = 1413102913279 ms
synInMethod endet
synInMethod beginnt, Zeit = 1413102915279 ms
synInMethod endet
synOnMethod beginnt, Zeit = 1413102917279 ms
synOnMethod endet
synInMethod beginnt, Zeit = 1413102919279 ms
synInMethod endet
synOnMethod beginnt, Zeit = 1413102921279 ms
synOnMethod endet
synOnMethod beginnt, Zeit = 1413102923279 ms
synOnMethod endet
Wie Sie sehen, erfolgt die Ausgabe der beiden streng seriell (ob bei der erneuten Ausführung zuerst synInMethod oder synOnMethod ausgeführt wird, hängt natürlich nicht davon ab, wer die Sperre erhält).
Fazit: Die beiden Sperrmethoden stehen in einer Konkurrenzbeziehung und können nur eine Methode gleichzeitig ausführen.