90 votes

Est-il sûr d'appeler une méthode synchronisée à partir d'une autre méthode synchronisée ?

Si une méthode synchronisée appelle une autre méthode synchronisée, est-elle thread safe ?

void synchronized method1() {
     method2()
}

void synchronized method2() {
}

112voto

pickypg Points 8948

Oui, lorsque vous marquez les méthodes comme synchronized alors vous le faites vraiment :

void method1() {
    synchronized (this) {
        method2()
    }
}

void method2() {
    synchronized (this) {
    }
}

Lorsque l'appel du thread entre dans la méthode 2 à partir de la méthode 1, il s'assurera qu'il détient le verrou de la méthode 1. this ce qu'il fera déjà, et il pourra alors passer à travers.

Lorsque le thread entre directement dans la méthode1 ou la méthode2, il se bloque jusqu'à ce qu'il puisse obtenir le verrou ( this ), puis il entrera.

Comme l'a noté James Black dans les commentaires, vous devez faire attention à ce que vous faites à l'intérieur du corps de la méthode.

private final List<T> data = new ArrayList<T>();

public synchronized void method1() {
    for (T item : data) {
        // ..
    }
}

public void method3() {
    data.clear();
}

Soudainement, ce n'est pas sûr parce que vous regardez un ConcurrentModificationException dans votre avenir parce que method3 n'est pas synchronisé, et peut donc être appelé par le fil A pendant que le fil B travaille dans l'application method1 .

7voto

Stephen C Points 255558

Une méthode marquée avec synchronized call une autre méthode synchronisée est-elle thread safe.

En général, il n'est pas possible de dire. Cela dépend de ce que font les méthodes, et de ce que font les autres méthodes de la même classe et d'autres classes.

Cependant, nous pouvons être sûrs que les appels à la méthode1 et à la méthode2 sur le même objet effectués par différents threads ne s'exécuteront pas simultanément. En fonction de ce que font les méthodes, cela mai est suffisant pour dire que la classe est thread-safe en ce qui concerne ces méthodes.

3voto

Stephen Lee Points 33

Extrait du site Tutoriels Java http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

  1. Il n'est pas possible que deux invocations de méthodes synchronisées sur le même objet s'entrelacent. Lorsqu'un thread exécute une méthode synchronisée pour un objet, tous les autres threads qui invoquent des méthodes synchronisées pour le même objet bloquent (suspendent l'exécution) jusqu'à ce que le premier thread ait terminé avec l'objet.

  2. lorsqu'une méthode synchronisée sort, elle établit automatiquement une relation happens-before avec toute invocation ultérieure d'une méthode synchronisée pour le même objet. Cela garantit que les changements d'état de l'objet sont visibles pour tous les threads.

Ainsi, Java s'assurera que si deux threads exécutent la même méthode, les méthodes ne seront pas exécutées en même temps mais l'une après l'autre.

Mais vous devez être conscient du problème de lividité, http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html

Et aussi si vous verrouillez inutilement, car dans le code que vous avez utilisé ce Si votre objet n'a besoin d'un accès synchrone qu'à une seule variable, il suffit de verrouiller cette variable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X