Question

Je me demandais si, en Java, j'aurais un comportement étrange si je synchronisais deux fois sur le même objet?

Le scénario est le suivant

pulbic class SillyClassName {

    object moo;
    ...
    public void method1(){
        synchronized(moo)
        {
            ....
            method2();
            ....
        }
    }

    public void method2(){
        synchronized(moo)
        {
            doStuff();
        }
    }
}

Les deux méthodes utilisent l'objet et sont synchronisées dessus. La seconde méthode appelée par la première méthode s’arrête-t-elle car elle est verrouillée?

Je ne pense pas, car c'est le même sujet, mais je ne suis pas certain qu'il puisse en résulter d'autres résultats étranges.

Était-ce utile?

La solution

Réentrant

Les blocs

synchronisés utilisent des verrous reentrant , ce qui signifie que si le thread le détient déjà, il peut le ré-acquérir sans problèmes. Par conséquent, votre code fonctionnera comme prévu.

Voir le bas de la Didacticiel Java page Verrous et synchronisation intrinsèques .

Citation à partir de 2015-01 & # 8230;

  

Synchronisation réentrante

     

Rappelez-vous qu’un thread ne peut pas acquérir un verrou appartenant à un autre thread. Mais un thread peut acquérir un verrou qu'il possède déjà. Autoriser un thread à acquérir plusieurs fois le même verrou active la synchronisation réentrante . Cela décrit une situation dans laquelle le code synchronisé, directement ou indirectement, appelle une méthode contenant également du code synchronisé et où les deux ensembles de codes utilisent le même verrou. Sans synchronisation réentrante, le code synchronisé devrait prendre de nombreuses précautions supplémentaires pour éviter qu'un thread ne se bloque.

Autres conseils

Je pense que nous devons utiliser le verrouillage réentrant pour ce que vous essayez de faire. Voici un extrait de http: //docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html .

  

Qu'entendons-nous par un verrou réentrant? Le nombre d'acquisitions est simplement associé au verrou, et si un thread qui détient le verrou l'acquiert à nouveau, le compte d'acquisition est incrémenté et le verrou doit ensuite être relâché deux fois pour libérer réellement le verrou. Ceci est parallèle à la sémantique de synchronisé; si un thread entre dans un bloc synchronisé protégé par un moniteur qu'il possède déjà, le thread sera autorisé à continuer et le verrou ne sera pas libéré lorsque le thread quittera le deuxième bloc (ou les suivants) synchronisé, mais seulement sera libéré. lorsqu’il quitte le premier bloc synchronisé, il est entré protégé par ce moniteur.

Bien que je n’aie pas essayé, je suppose que si vous voulez faire ce que vous avez décrit ci-dessus, vous devez utiliser un verrou ré-entrant.

Java semble prendre totalement en charge les verrous imbriqués sur un objet du même thread. Cela signifie que si un thread a un verrou externe et un verrou interne sur un objet et qu'un autre thread tente de se verrouiller sur le même objet, le second thread sera suspendu jusqu'à ce que les deux verrous aient été libérés par le premier. fil.

Mes tests ont été réalisés sous Java 6 SE.

Pas de problèmes. Dans votre exemple (une fois que vous corrigez le code pour vous débarrasser des avertissements de compilation que vous obtiendrez;)), la synchronisation garantit que les blocs de method1 et method2 ne seront pas exécutés simultanément.

C'est un peu le point de synchronisation. :)

Edit: Désolé, vous avez manqué des parties de votre question, mais Phill y a répondu. Pour résumer, un seul thread ne peut pas se bloquer.

En java, le mot clé synchronized d'une méthode se synchronise essentiellement sur l'objet actuel. En réalité, il fait ce que vous suggérez implicitement.

Vous ne rencontrerez pas de problèmes de synchronisation sur un objet d'une méthode puis sur le même objet d'une autre méthode car, comme vous le dites, le thread actuel détient déjà le verrou sur cet objet.

Non, la deuxième méthode ne s’arrêtera pas si elle est appelée en premier. Aucun résultat étrange ne se produira (à l'exception d'un léger surcoût lié à la vérification du verrouillage. Cela importera peu. Java 6 et versions ultérieures, vous obtenez un verrouillage grossier dans la machine virtuelle - http://java.sun.com/performance/reference/whitepapers/6_performance.html )

Par exemple, examinez le code source de java.util.Vector. Il y a beaucoup d'appels à d'autres méthodes synchronisées à partir de méthodes synchronisées.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top