Sobes.tech
Middle+

Comment fonctionne le mécanisme de synchronisation 'synchronized' en Java en coulisses?

sobes.tech IA

Réponse de l'IA

Le mécanisme synchronized en Java est basé sur le concept de moniteurs (objets moniteurs). Chaque objet en Java est associé à un moniteur.

Lorsqu'un thread entre dans un bloc ou une méthode synchronisée, il tente d'acquérir le moniteur de l'objet correspondant. Si le moniteur est libre, le thread l'acquiert et continue l'exécution. Si le moniteur est occupé par un autre thread, le thread actuel est bloqué et passe en état d'attente jusqu'à ce que le moniteur soit libéré.

Lorsqu'un thread quitte un bloc ou une méthode synchronisée (que ce soit en la terminant avec succès ou en lançant une exception), il libère le moniteur.

À l'intérieur du moniteur, sont implémentés :

  1. Exclusion mutuelle (Mutual Exclusion) : Un seul thread peut posséder le moniteur d'un objet à un moment donné. Cela garantit qu'un seul thread peut exécuter du code synchronisé pour cet objet.
  2. Attente et notification (Waiting and Notification) : Le moniteur inclut un ensemble de méthodes associées wait(), notify() et notifyAll(). Ces méthodes permettent aux threads qui possèdent le moniteur de le libérer temporairement et de passer en état d'attente, puis d'être notifiés par d'autres threads de la possibilité de continuer.

L'implémentation en dessous comprend :

  • Instruction monitorenter : Exécutée lors de l'entrée dans un bloc ou une méthode synchronisée. Tente d'acquérir le moniteur de l'objet.
  • Instruction monitorexit : Exécutée lors de la sortie d'un bloc ou d'une méthode synchronisée (que ce soit par une terminaison normale ou une exception). Libère le moniteur de l'objet.

Ces instructions font partie du bytecode Java et sont traitées par la machine virtuelle Java (JVM). La JVM utilise des mécanismes natifs du système d'exploitation (comme mutex, sémaphores) pour gérer les moniteurs et le verrouillage/déverrouillage des threads.

L'acquisition du moniteur peut être implémentée au niveau de l'objet (pour les méthodes et blocs d'instance) ou au niveau de la classe (pour les méthodes et blocs statiques), en utilisant l'objet Class comme verrou.

Exemple d'utilisation :

public class Counter {
    private int count = 0;

    public synchronized void increment() { // Méthode synchronisée
        count++;
    }

    public void decrement() {
        synchronized (this) { // Bloc synchronisé
            count--;
        }
    }

    public static synchronized void staticMethod() { // Méthode statique synchronisée
        // ...
    }
}

Tableau des méthodes de la classe Object liées aux moniteurs :

Méthode Description
wait() Le thread possédant le moniteur le libère temporairement et passe en attente.
notify() Notifie un des threads en attente qu'il peut tenter d'acquérir le moniteur et continuer.
notifyAll() Notifie tous les threads en attente.