Attenti al synchronized

La chiave synchronized è sicuramente la più usata quando vi è la necessità di gestire gli accessi concorrenti ad una porzione di codice. L’utilizzo di questa parola chiave ha però un costo elevato perchè lo scheduler della JVM deve pianificare degli accessi serializzati (cioè sequenziali) al blocco di codice e non concorrenti come di solito avviene, creando quindi delle possibili situazioni di stallo ed inoltre la JVM ha il costo del mantenimento della coda di thread in attesa, creando seri problemi di performance e scalabilità ai nostri applicativi.

Per iniziare una delle cose peggiori che possiamo fare è sincronizzare metodi o variabili statiche.
Facendo questo infatti inibiamo accessi concorrenti per tutte le istanze di quella classe.

Parlato del male più totale passiamo ad uno dei primi accorgimenti che si possono attuare nell’uso della parola chiave syncronized è il sincronizzare il minor codice possibile, quindi è meglio evitare l’utilizzo di questa parola nella firma di un metodo perchè in questo modo sarà bloccatto l’accesso concorrente a tutto l’oggetto, è quindi meglio l’uso del synchronized block:

public methodName(){
String a = “abcdefg”;

synchronized(variable){

}

}

Nell’esempio viene sincronizzato solo un blocco del codice e non l’intero oggetto, quindi si riduce il tempo in cui l’oggetto non accetterà accessi concorrenti, tanto a noi interessa solo proteggere modifiche concorrenti alla variabile variable (che fantasia che ho 😀 ).

Il synchronized nella maggioranza dei casi viene utilizzato per gestire accessi concorrenti ad una variabile, come ad esempio può essere l’incremento di un contatore e forse questo vi stupirà, ma proprio in casi come questo possiamo farne. Essì cari miei si può uscire dal tunnel del synchronized. Per riuscire in ciò bisogna ricorrere ad una tecnica denominata compare-and-swap (CAS).

Questa tecnica utilizza tre parametri: una locazione di memoria, il vecchio valore che si crede di trovare ed il nuovo valore da impostare. Il sistema aggiornerà la locazione di memoria al nuovo valore solo se il vecchio valore corrisponde a quello che ci si aspetta:

public int increment() {
int oldValue = value.getValue();
int newValue = oldValue + 1;
while (value.compareAndSwap(oldValue, newValue) != oldValue)
oldValue = value.getValue();
return oldValue + 1;
}

Questo esempio può far capire un po’ meglio come funziona CAS, ma nella maggioranza dei casi non toccherà a noi scrivere codice come il seguente per Java SE dalla versione 5.0 in poi ci viene in aiuto con il package java.util.concurrent.atomic che contiene diversi tipi che già utlizzano CAS.
Questi per esempio sono: AtomicInteger, AtomicLong, AtomicReference, AtomicBoolean, alcuni array formati da questi tipi ed altri ancora.
Utilizzando queste classi diventa tutto più semplice, infatti il metodo incremente visto sopra potrebbe essere scritto così:

private AtomicInteger value = new AtomicInteger(0);
public int ingrement(){
return value.getAndIncrement();
}

Questo approccio anche se può sembrare pià complicato è in verità più semplice, perchè anche se 49 thread dovessero provare ad incrementare il valore farebbero al massimo 50 richieste, che fidate pesano molto meno di 49 richieste in attesa su un blocco di codice synchronized.

Annunci

~ di jesty su luglio 8, 2008.

4 Risposte to “Attenti al synchronized”

  1. fai ridere

    • almeno io faccio qualcosa 🙂
      e non lascio commenti anonimi a criticare chi fa qualcosa: sai quelle cose come metterci la faccia, coraggio di esporsi in prima persona e così via.
      se ti va di motivare questo commento sarò lieto di rispondere

  2. grazie… lo trovo interessante, ciao..

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

 
%d blogger hanno fatto clic su Mi Piace per questo: