I programmi multi-thread possono spesso arrivare a una situazione in cui più thread tentano di accedere alle stesse risorse e alla fine producono risultati errati e imprevisti.
Perché utilizzare la sincronizzazione Java?
La sincronizzazione Java viene utilizzata per garantire, tramite un metodo di sincronizzazione, che solo un thread possa accedere alla risorsa in un determinato momento.
matrice di lattice
Blocchi sincronizzati Java
Java fornisce un modo per creare thread e sincronizzare le loro attività utilizzando blocchi sincronizzati.
Un blocco sincronizzato in Java è sincronizzato su alcuni oggetti. Tutti i blocchi sincronizzati si sincronizzano sullo stesso oggetto e al loro interno può essere eseguito un solo thread alla volta. Tutti gli altri thread che tentano di entrare nel blocco sincronizzato vengono bloccati finché il thread all'interno del blocco sincronizzato non esce dal blocco.
Nota: I blocchi sincronizzati in Java sono contrassegnati con la parola chiave sincronizzata.
Forma generale del blocco sincronizzato
// Only one thread can execute at a time. // sync_object is a reference to an object // whose lock associates with the monitor . // The code is said to be synchronized on // the monitor object synchronized(sync_object) { // Access shared variables and other // shared resources }> Questa sincronizzazione è implementata in Java con un concetto chiamato monitor o lock. Solo un thread può possedere un monitor alla volta. Quando un thread acquisisce un lock, si dice che sia entrato nel monitor. Tutti gli altri thread che tentano di accedere al monitor bloccato verranno sospesi finché il primo thread non esce dal monitor.
Tipi di sincronizzazione
Esistono due sincronizzazioni in Java menzionate di seguito:
- Sincronizzazione dei processi
- Sincronizzazione dei thread
1. Sincronizzazione dei processi in Java
La sincronizzazione dei processi è una tecnica utilizzata per coordinare l'esecuzione di più processi. Garantisce che le risorse condivise siano sicure e in ordine.
2. Sincronizzazione dei thread in Java
La sincronizzazione dei thread viene utilizzata per coordinare e ordinare l'esecuzione dei thread in un programma multi-thread. Esistono due tipi di sincronizzazione dei thread menzionati di seguito:
- Mutua esclusiva
- Cooperazione (comunicazione inter-thread in Java)
Mutua esclusiva
L'esclusione reciproca aiuta a evitare che i thread interferiscano tra loro durante la condivisione dei dati. Esistono tre tipi di mutua esclusiva menzionati di seguito:
- Metodo sincronizzato.
- Blocco sincronizzato.
- Sincronizzazione statica.
Esempio di sincronizzazione
Di seguito è riportata l'implementazione della sincronizzazione Java:
Giava
sincronizzare Java
// A Java program to demonstrate working of> // synchronized.> import> java.io.*;> import> java.util.*;> // A Class used to send a message> class> Sender {> >public> void> send(String msg)> >{> >System.out.println(>'Sending '> + msg);> >try> {> >Thread.sleep(>1000>);> >}> >catch> (Exception e) {> >System.out.println(>'Thread interrupted.'>);> >}> >System.out.println(>'
'> + msg +>'Sent'>);> >}> }> // Class for send a message using Threads> class> ThreadedSend>extends> Thread {> >private> String msg;> >Sender sender;> >// Receives a message object and a string> >// message to be sent> >ThreadedSend(String m, Sender obj)> >{> >msg = m;> >sender = obj;> >}> >public> void> run()> >{> >// Only one thread can send a message> >// at a time.> >synchronized> (sender)> >{> >// synchronizing the send object> >sender.send(msg);> >}> >}> }> // Driver class> class> SyncDemo {> >public> static> void> main(String args[])> >{> >Sender send =>new> Sender();> >ThreadedSend S1 =>new> ThreadedSend(>' Hi '>, send);> >ThreadedSend S2 =>new> ThreadedSend(>' Bye '>, send);> >// Start two threads of ThreadedSend type> >S1.start();> >S2.start();> >// wait for threads to end> >try> {> >S1.join();> >S2.join();> >}> >catch> (Exception e) {> >System.out.println(>'Interrupted'>);> >}> >}> }> |
>
logica del primo ordine
>Produzione
parafrasare se di Rudyard Kipling
Sending Hi Hi Sent Sending Bye Bye Sent>
L'output è lo stesso ogni volta che eseguiamo il programma.
Spiegazione
Nell'esempio sopra, scegliamo di sincronizzare l'oggetto Sender all'interno del metodo run() della classe ThreadedSend. In alternativa, potremmo definire the l'intero blocco send() come sincronizzato , producendo lo stesso risultato. Quindi non dobbiamo sincronizzare l'oggetto Message all'interno del metodo run() nella classe ThreadedSend.
// An alternate implementation to demonstrate // that we can use synchronized with method also. class Sender { public synchronized void send(String msg) { System.out.println('Sending ' + msg); try { Thread.sleep(1000); } catch (Exception e) { System.out.println('Thread interrupted.'); } System.out.println('
' + msg + 'Sent'); } }> Non è sempre necessario sincronizzare un intero metodo. A volte è preferibile sincronizzare solo parte di un metodo . I blocchi sincronizzati Java all'interno dei metodi lo rendono possibile.
// One more alternate implementation to demonstrate // that synchronized can be used with only a part of // method class Sender { public void send(String msg) { synchronized(this) { System.out.println('Sending ' + msg ); try { Thread.sleep(1000); } catch (Exception e) { System.out.println('Thread interrupted.'); } System.out.println('
' + msg + 'Sent'); } } }> Esempio del metodo sincronizzato utilizzando una classe anonima
Giava
// Java Pogram to synchronized method by> // using an anonymous class> import> java.io.*;> class> Test {> >synchronized> void> test_function(>int> n)> >{> >// synchronized method> >for> (>int> i =>1>; i <=>3>; i++) {> >System.out.println(n + i);> >try> {> >Thread.sleep(>500>);> >}> >catch> (Exception e) {> >System.out.println(e);> >}> >}> >}> }> // Driver Class> public> class> GFG {> >// Main function> >public> static> void> main(String args[])> >{> >// only one object> >final> Test obj =>new> Test();> >Thread a =>new> Thread() {> >public> void> run() { obj.test_function(>15>); }> >};> >Thread b =>new> Thread() {> >public> void> run() { obj.test_function(>30>); }> >};> >a.start();> >b.start();> >}> }> |
cambia metodo java
>
>Produzione
16 17 18 31 32 33>