Wenn eine synchronisierte Methode eine andere synchronisierte Methode aufruft, ist sie threadsicher?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
java
thread-safety
user705414
quelle
quelle
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, weilmethod3
es nicht synchronisiert ist und daher von Thread A aufgerufen werden kann, während Thread B arbeitetmethod1
.quelle
method3
Zeigt unsichere Threading-Vorgänge an, aber Sie sind genau über die Wiedereintrittssynchronisation informiert.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.
quelle
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.
quelle
synchronized (this.someVar)
Sie schauen auf das Objekt, in dem sich die Referenz befindetsomeVar
. Die Unterscheidung ist sehr wichtig.