Singleton – Thread Safety

Il singleton è sicuro il design pattern più conosciuto e più facile da implementare, indipendentemente dal linguaggio di programmazione che si sta usando. Per creare una classe singleton basta seguire i seguenti tre step:

  • Dichiarare il costruttore privato in modo da evitare che si creino più istanze della classe Singleton.
  • Dichiarare una variabile privata statica della classe singleton
  • Creare un metodo public che ritornerà la variabile statica della classe singleton. Se la variabile non è inizializzata viene inizializzata altrimenti semplicemente il metodo ritorna la variabile.

Demo.java

package com.devblog.designpatterns;
public class Demo {
	private static Demo instance = null;
	private Demo() {}
	public static Demo getInstance() {
		if (instance == null) {
			instance = new Demo();
		}
		return instance;
	}
}

Abbiamo creato il nostro singleton, adesso garantiamo che la classe Demo abbia una sola istanza all’interno del nostro progetto. Ma cosa succede se si lavora in ambiente multithreading? Per come è strutturato il metodo getIstance() non garantisce, in ambiente multithreading, una sola istanza della classe singleton ovvero si dice che il metodo getInstance non è Thread-safe. Infatti più thread possono accedervi, e per i primi thread, quando la variabile d’istanza non è inizializzata, più thread possono entrare nell’ if e creare più istanze della classe Demo.

Soluzioni

Ci sono diversi modi per rendere il metodo getInstance() thread-safe io ve ne mostrerò tre, parlandovi anche dei pro e dei contro:

1. Creare l’istanza della variabile al tempo di caricamento della classe

private static final Demo instance = new Demo();

Pro:

      • Garantiamo il thread-safe senza sincronizzazione
      • Molto semplice da implementare

Contro:

      • L’istanza creata potrebbe non essere usata all’interno dell’applicazione

2. Aggiungere synchronized al metodo getInstance()
Pro:

      • Garantiamo il thread-safe
      • Molto semplice da implementare

Contro:

      • Le performance dell’applicazione potrebbero risentirne

3. Usare synchronized nel blocco if e la variabile volatile
Pro:

      • Thread safety garantito
      • L’overhead di sincronizzazione è minimale e applicabile solo la prima volta

Contro:

      • Codice più complesso e condizioni di if innestati

 

package com.devblog.designpatterns;

public class Demo {

	private static volatile Demo instance;

	private Demo() {
	}

	public static Demo getInstance() {
		if (instance == null) {
			synchronized (Demo.class) {
				if (instance == null)
					instance = new Demo();
			}
		}
		return instance;
	}

}

Link utili:

Keyword volatile

About the Author

aparzi

aparzi

Fondatore di questo blog e studente di Informatica presso l' Università degli Studi del Molise, contemporaneamente lavoro alla Xeos.it come Software Developer utilizzando tecnologie quali Java e Spring-Boot. Nel mio tempo libero mi piace imparare nuove tecnologie soprattutto lato frontend, come React oppure Angular. Sono sempre stato un appassionato del mondo dell' informatica e ho un debole per il sistema operativo Linux.

Leave a Reply

Your email address will not be published. Required fields are marked *