Sincronizzazione in Java | Spiegato

Sincronizzazione in Java | Spiegato
Quando iniziamo due o più thread nello stesso programma, esiste la possibilità che i thread multipli tengano di accedere alla stessa risorsa e, di conseguenza, verranno prodotti risultati incoerenti. E al fine di fornire una comunicazione affidabile tra i thread multipli, il concetto di sincronizzazione viene utilizzato in Java. La parola chiave sincronizzata in java sincronizza le azioni di più thread e si assicura che un solo thread possa accedere a una risorsa specifica in un determinato momento.

Questo articolo esplorerà i vari aspetti della sincronizzazione in Java e in questo senso, questo articolo coprirà i seguenti concetti:

  • Cos'è la sincronizzazione in Java?
  • Perché viene utilizzata la sincronizzazione?
  • Perché la parola chiave sincronizzata viene utilizzata in Java
  • Come usare la sincronizzazione in Java

Quindi, otteniamo

Cos'è la sincronizzazione in Java?

È un processo che controlla l'accesso di più di un thread a qualsiasi risorsa condivisa e quindi evita risultati incoerenti.

Perché viene utilizzata la sincronizzazione?

In Java, lo scopo principale di utilizzare la sincronizzazione è evitare il comportamento incoerente dei thread e prevenire l'interferenza dei fili.

Perché la parola chiave sincronizzata viene utilizzata in Java

Sincronizzato è un modificatore che può essere applicato solo sui metodi e sui blocchi e non può essere applicato su variabili e classi. Per capire questo concetto

Come usare la sincronizzazione in Java

Considereremo alcuni esempi per una profonda comprensione. Inizialmente, creeremo un programma Java molto semplice per incrementare il valore del contatore. Successivamente, estenderemo questo esempio allo scenario multithread. A poco a poco, ci dirigeremo verso la sincronizzazione dove impareremo perché la parola chiave sincronizzata viene utilizzata in Java?

Esempio
In questo esempio, creeremo un semplice programma che ha una variabile contatore e una funzione definita dall'utente incrementazione ().

Contriclasse di classe
conta contabile;
public void incrementValue ()
contatore ++;


Classe pubblica SynchronizationExample
public static void main (string [] args)
Count COUNT (new CounterClass ();
contare.incrementarValue ();
Sistema.fuori.println ("contatore:" + conteggio.contatore);

Ogni volta che invochiamo il incrementazione () Increterà il valore di contatore di 1:

Il valore del contatore viene incrementato con successo a 1 che mostra l'adeguatezza del nostro programma. Se chiamiamo il incrementazione () Metodo due volte, quindi il valore del contatore 2. Allo stesso modo, mostrerà il valore del contatore come 3 se chiamiamo il incrementazione () Metodo tre volte come mostrato nello snippet seguente:

Nel frammento di codice sopra, abbiamo invocato il incrementazione () Metodo quattro volte, quindi mostra il valore del contatore come 4.

Esempio
Ora, estendiamo un po 'l'esempio sopra in cui creeremo un thread che chiamerà l'incremento () dieci volte:

Contriclasse di classe
conta contabile;
public void incrementValue ()
contatore ++;


Classe pubblica SynchronizationExample
public static void main (string [] args) lancia l'eccezione
Count COUNT (new CounterClass ();
Thread Th1 = new Thread (new runNable ()
public void run ()
per (int i = 1; i <= 10; i++)
contare.incrementarValue ();


);
Th1.inizio();
Th1.giuntura();
Sistema.fuori.println ("contatore:" + conteggio.contatore);

Nel metodo di join () di code-snippet sopra viene utilizzato con l'oggetto della classe thread in modo che un thread debba attendere fino a quando l'altro thread completa l'esecuzione. Il code-snippet sopra produce il seguente output:

Dall'output è chiaro che il thread chiama il incrementazione () dieci volte e quindi il valore del contatore è uguale a dieci.

Finora tutto bene, ora consideriamo un ambiente multithread e creiamo un altro thread per vedere cosa accadrà quando due thread richiedono la stessa risorsa (i.e. incrementazione () metodo) allo stesso tempo.

Esempio

In questo esempio, abbiamo due thread che entrambi chiameranno il metodo incrementValue () cinquecento volte:

Contriclasse di classe
conta contabile;
public void incrementValue ()
contatore ++;


Classe pubblica SynchronizationExample
public static void main (string [] args) lancia l'eccezione
Count COUNT (new CounterClass ();
Thread Th1 = new Thread (new runNable ()
public void run ()
per (int i = 1; i <= 500; i++)
contare.incrementarValue ();


);
Thread Th2 = new Thread (new runNable ()
public void run ()
per (int i = 1; i <= 500; i++)
contare.incrementarValue ();


);
Th1.inizio();
Th1.giuntura();
Th2.inizio();
Th2.giuntura();
Sistema.fuori.println ("contatore:" + conteggio.contatore);

Poiché entrambi i thread chiamano il controvalore () cinquecento volte, tecnicamente il valore dell'incremento dovrebbe essere mille. Consideriamo lo snippet di seguito per vedere cosa dice l'output:

Invece di "1000", otteniamo "753", ora cosa significa? Perché non abbiamo ottenuto il valore del contatore di 1000?

Bene, è perché il multithreading supporta l'elaborazione parallela e quindi, esiste sempre la possibilità che entrambi i thread prendano il valore del contatore allo stesso tempo e quindi entrambi ottengono lo stesso valore di contatore, in tal caso invece di incrementare Valore del contatore due volte, incrementi solo una volta.

Quindi, come evitare uno scenario del genere? BENE! In tali casi, verrà utilizzata la parola chiave sincronizzata.

Esempio
Useremo la parola chiave sincronizzata con "incrementazione ()"Metodo di conseguenza solo un thread accederà al"incrementazione ()"Metodo contemporaneamente. Tutto il codice rimarrà lo stesso dell'esempio precedente che solo la parola chiave sincronizzata verrà aggiunta con il metodo IncrementValue () come mostrato nello snippet:

public sincronizzato void incrementValue ()
contatore ++;

Ora se il thread 1 sta lavorando con il incrementazione () Metodo quindi thread 2 aspetterà e viceversa. Questa volta otterremo il seguente output:

Lo snippet di cui sopra mostra l'efficacia della parola chiave "sincronizzata".

Conclusione

La sincronizzazione è un processo che controlla l'accesso di più di un thread e si assicura che solo un thread possa accedere alla risorsa in un determinato momento. Per ottenere la sincronizzazione, viene utilizzata la parola chiave/modificatore sincronizzata e può essere applicata ai metodi e ai blocchi ma non può essere applicata a variabili e classi. In Java, lo scopo principale di utilizzare la sincronizzazione è evitare il comportamento incoerente dei thread e prevenire l'interferenza dei fili.