Wenn eine synchronisierte Methode eine andere synchronisierte Methode aufruft, ist sie threadsicher?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
Wenn eine synchronisierte Methode eine andere synchronisierte Methode aufruft, ist sie threadsicher?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
Antworten:
Ja, wenn Sie Methoden als markieren synchronized
, tun Sie dies wirklich:
void method1() {
synchronized (this) {
method2()
}
}
void method2() {
synchronized (this) {
}
}
Wenn der Thread-Aufruf von Methode1 in Methode2 gelangt, stellt er sicher, dass er die Sperre hält this
, an der er sich bereits befindet, und kann dann durchlaufen.
Wenn der Thread direkt in Methode1 oder Methode2 gelangt, wird er blockiert, bis er die Sperre ( this
) erhalten kann, und dann wird er eingegeben.
Wie von James Black in den Kommentaren bemerkt, müssen Sie sich darüber im Klaren sein, was Sie innerhalb des Methodenkörpers tun.
private final List<T> data = new ArrayList<T>();
public synchronized void method1() {
for (T item : data) {
// ..
}
}
public void method3() {
data.clear();
}
Plötzlich ist es nicht threadsicher, weil Sie ConcurrentModificationException
in Zukunft auf a schauen, weil method3
es nicht synchronisiert ist und daher von Thread A aufgerufen werden kann, während Thread B arbeitet method1
.
method3
Zeigt unsichere Threading-Vorgänge an, aber Sie sind genau über die Wiedereintrittssynchronisation informiert.
Ist eine mit synchronisiertem Aufruf gekennzeichnete Methode ein weiterer synchronisierter Methoden-Thread sicher?
Im Allgemeinen ist es nicht möglich zu sagen. Dies hängt davon ab, was die Methoden tun und welche anderen Methoden in derselben und anderen Klassen.
Wir können jedoch sicher sein, dass Aufrufe von Methode1 und Methode2 für dasselbe Objekt, die von verschiedenen Threads ausgeführt werden, nicht gleichzeitig ausgeführt werden. Je nachdem, was die Methoden tun, kann dies ausreichen, um zu sagen, dass die Klasse in Bezug auf diese Methoden threadsicher ist.
Von der Java Tutorials-Website http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Es ist nicht möglich, dass zwei Aufrufe synchronisierter Methoden für dasselbe Objekt verschachtelt werden. Wenn ein Thread eine synchronisierte Methode für ein Objekt ausführt, blockieren alle anderen Threads, die synchronisierte Methoden für denselben Objektblock aufrufen (Ausführung aussetzen), bis der erste Thread mit dem Objekt fertig ist.
Wenn eine synchronisierte Methode beendet wird, wird automatisch eine Vorher-Beziehung zu einem nachfolgenden Aufruf einer synchronisierten Methode für dasselbe Objekt hergestellt. Dies garantiert, dass Änderungen am Status des Objekts für alle Threads sichtbar sind
Java stellt also sicher, dass, wenn zwei Threads dieselbe Methode ausführen, die Methoden nicht gleichzeitig, sondern nacheinander ausgeführt werden.
Sie müssen sich jedoch des Liveness-Problems bewusst sein: http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
Und auch , ob Sie uncessarily sind blockiert, weil im Code verwendet man diese , die das ganze Objekt sperrt, wenn das Objekt nur sync Zugriff auf eine Variable benötigt , sollten Sie nur diese Variable sperren.
synchronized (this.someVar)
Sie schauen auf das Objekt, in dem sich die Referenz befindet someVar
. Die Unterscheidung ist sehr wichtig.