Sobes.tech
Middle+

Come funziona il meccanismo di sincronizzazione 'synchronized' in Java sotto il cofano?

sobes.tech AI

Risposta dell'AI

Il meccanismo synchronized in Java si basa sul concetto di monitor (oggetti monitor). A ogni oggetto in Java è associato un monitor.

Quando un thread entra in un blocco o metodo sincronizzato, tenta di acquisire il monitor dell'oggetto corrispondente. Se il monitor è libero, il thread lo acquisisce e continua l'esecuzione. Se il monitor è occupato da un altro thread, il thread corrente viene bloccato e passa in uno stato di attesa finché il monitor non viene rilasciato.

Quando un thread esce da un blocco o metodo sincronizzato (sia terminandolo con successo che lanciando un'eccezione), rilascia il monitor.

All'interno del monitor sono implementati:

  1. Esclusione mutua (Mutual Exclusion): Solo un thread può possedere il monitor di un oggetto in un dato momento. Questo garantisce che solo un thread possa eseguire codice sincronizzato per quell'oggetto.
  2. Attesa e notifica (Waiting and Notification): Il monitor include un insieme di metodi associati wait(), notify() e notifyAll(). Questi metodi permettono ai thread che possiedono il monitor di rilasciarlo temporaneamente e passare in uno stato di attesa, e poi essere notificati da altri thread sulla possibilità di continuare.

L'implementazione a basso livello include:

  • Istruzione monitorenter: Esegue all'ingresso in un blocco o metodo sincronizzato. Tenta di acquisire il monitor dell'oggetto.
  • Istruzione monitorexit: Esegue all'uscita da un blocco o metodo sincronizzato (sia per terminazione normale che per eccezione). Rilascia il monitor dell'oggetto.

Queste istruzioni fanno parte del bytecode Java e sono gestite dalla macchina virtuale Java (JVM). La JVM utilizza meccanismi nativi del sistema operativo (come mutex, semafori) per gestire i monitor e il blocco/sblocco dei thread.

L'acquisizione del monitor può essere implementata a livello di oggetto (per metodi e blocchi di istanza) o a livello di classe (per metodi e blocchi statici), usando l'oggetto Class come blocco.

Esempio di utilizzo:

public class Counter {
    private int count = 0;

    public synchronized void increment() { // Metodo sincronizzato
        count++;
    }

    public void decrement() {
        synchronized (this) { // Blocco sincronizzato
            count--;
        }
    }

    public static synchronized void staticMethod() { // Metodo statico sincronizzato
        // ...
    }
}

Tabella dei metodi della classe Object correlati ai monitor:

Metodo Descrizione
wait() Il thread che possiede il monitor lo rilascia temporaneamente e passa in attesa.
notify() Notifica a uno dei thread in attesa che può tentare di acquisire il monitor e continuare.
notifyAll() Notifica tutti i thread in attesa.