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:
- 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.
- Attesa e notifica (Waiting and Notification): Il monitor include un insieme di metodi associati
wait(),notify()enotifyAll(). 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. |