150 votes

Méthodes statiques synchronisées de Java : verrouillage sur un objet ou une classe

La documentation Java dit :

Il n'est pas possible que deux invocations de méthodes synchronisées sur le même ordinateur puissent avoir lieu. même objet.

Qu'est-ce que cela signifie pour une méthode statique ? Puisqu'une méthode statique n'a pas d'objet associé, le mot-clé synchronisé se verrouillera-t-il sur la classe, au lieu de l'objet ?

202voto

Cowan Points 17235

Pour ajouter un petit détail à la réponse (agréablement succincte !) d'Oscar, la section pertinente de la spécification du langage Java est la suivante 8.4.3.6, "Méthodes synchronisées". :

Une méthode synchronisée acquiert un moniteur ( §17.1 ) avant qu'il ne soit exécuté. Pour une méthode de classe (statique), le moniteur associé à l'objet Class de la classe de la méthode est utilisé. Pour une méthode d'instance, c'est le moniteur associé à this (l'objet pour lequel la méthode a été invoquée) qui est utilisé.

17 votes

Utile, je cherchais cette citation +1

132voto

OscarRyz Points 82553

Puisqu'une méthode statique n'a pas d'objet associé, le mot-clé synchronisé va-t-il verrouiller la classe, au lieu de l'objet ?

Oui. :)

82 votes

Veuillez répondre en élaborant de manière à ce que tout le monde puisse comprendre.

6 votes

@Madhu. Cela signifie que si vous avez 2 ou plusieurs méthodes synchronisées sur la même classe, les deux ne peuvent pas s'exécuter en même temps, même s'il y a plusieurs instances de cette classe. Le verrouillage est essentiellement le même que le verrouillage sur la classe Object.class pour chaque méthode synchronisée.

0 votes

Cette réponse est fausse - this est le verrou acquis sur les méthodes d'instance-, merci de le corriger Oscar.

80voto

jfpoilpret Points 6523

Un point auquel il faut faire attention (plusieurs programmeurs tombent généralement dans ce piège) est qu'il n'y a pas de lien entre les méthodes statiques synchronisées et les méthodes non statiques synchronisées, c'est à dire :

class A {
    static synchronized f() {...}
    synchronized g() {...}
}

Principal :

A a = new A();

Fil conducteur 1 :

A.f();

Le fil 2 :

a.g();

f() et g() ne sont pas synchronisées l'une avec l'autre et peuvent donc s'exécuter de manière totalement concurrente.

18 votes

Mais que faire si g() modifie une variable statique que f() lit. Comment rendre ce thread sûr ? Devons-nous acquérir explicitement un verrou sur la classe ?

22 votes

Oui, votre méthode non statique doit être explicitement synchronisée sur la classe elle-même (c'est-à-dire qu'elle doit être synchronisée sur la classe elle-même), synchronized (MyClass.class) {...} .

0 votes

@jfpoilpret "synchronized (MyClass.class) {...}" est équivalent à rendre cette méthode synchronisée statique, non ?

15voto

Sauf si vous implémentez g() comme suit :

g() {
    synchronized(getClass()) {
        ...
    }
}

Je trouve ce modèle utile également lorsque je veux mettre en œuvre l'exclusion mutuelle entre différentes instances de l'objet (ce qui est nécessaire pour accéder à une ressource externe, par exemple).

4voto

Ravindra babu Points 5571

Consultez la page de documentation d'oracle sur Verrous intrinsèques et synchronisation

Vous pouvez vous demander ce qui se passe lorsqu'une méthode statique synchronisée est invoquée, puisqu'une méthode statique est associée à une classe, et non à un objet. Dans ce cas, le thread acquiert le verrou intrinsèque de l'objet Class associé à la classe . Ainsi, l'accès aux champs statiques de la classe est contrôlé par un verrou distinct du verrou de toute instance de la classe. .

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