Guida alla sincronizzazione in Java

Pubblicato: 2022-10-23

Prima di spiegare la sincronizzazione in Java , dobbiamo rivisitare brevemente il concetto di multithreading. La funzione multithreading di Java consente l'esecuzione simultanea di due o più parti di un programma per il massimo utilizzo della CPU. Ogni parte di un tale programma è un thread e i thread sono processi leggeri all'interno di un processo.

Ora, più thread di un programma potrebbero tentare di accedere alle stesse risorse e produrre risultati imprecisi. Quindi, deve esserci una certa sincronizzazione per garantire che solo un thread abbia accesso alle risorse in un determinato momento.

Dai un'occhiata ai nostri corsi di tecnologia gratuiti per avere un vantaggio sulla concorrenza.

Questa guida su cos'è la sincronizzazione in Java esplorerà il concetto di sincronizzazione in dettaglio con esempi.

Impara i corsi di sviluppo software online dalle migliori università del mondo. Guadagna programmi Executive PG, programmi di certificazione avanzati o programmi di master per accelerare la tua carriera.

Sommario

Che cos'è la sincronizzazione in Java?

La sincronizzazione Java è la capacità di controllare l'accesso di più thread a una risorsa condivisa. È utile quando i programmi Java multi-thread tentano di accedere alla stessa risorsa e producono risultati errati. Utilizzando la funzione di sincronizzazione Java, solo un singolo thread può accedere alla risorsa in un determinato momento.

Java fornisce un modo per sincronizzare l'attività dei thread utilizzando blocchi sincronizzati che si sincronizzano sullo stesso oggetto e possono avere un solo thread in esecuzione al loro interno alla volta. Questi blocchi sono contrassegnati con la parola chiave sincronizzata, bloccando qualsiasi altro thread che tenta di entrare nel blocco sincronizzato fino a quando il thread già all'interno del blocco termina la sua esecuzione e lascia il blocco.

Dai un'occhiata alla certificazione avanzata di upGrad in DevOps

La sintassi per scrivere un blocco sincronizzato

La sintassi generale per scrivere un blocco sincronizzato in Java è la seguente:

sincronizzato( lockObject )

{

// istruzioni sincronizzate

}

Esplora i nostri corsi di ingegneria del software popolari

Master of Science in Informatica presso LJMU e IIITB Programma di certificazione di sicurezza informatica Caltech CME
Bootcamp di sviluppo full stack Programma PG in Blockchain
Programma Executive PG in Full Stack Development
Visualizza tutti i nostri corsi qui sotto
Corsi di ingegneria del software

Nella sintassi precedente, lockObject si riferisce a un oggetto il cui lock è correlato agli elementi sincronizzati. Ora, questo ci porta al concetto di blocco in Java.

Dai un'occhiata alla certificazione avanzata di upGrad in sicurezza informatica

Si blocca in Java

La sincronizzazione in Java è costruita attorno al blocco o al monitor. Ogni oggetto ha un lucchetto associato. Idealmente, un thread che richiede l'accesso ai campi di un oggetto deve prima ottenere il blocco dell'oggetto. Il blocco è un meccanismo di sincronizzazione dei thread più sofisticato e flessibile rispetto al blocco di sincronizzazione. È definito all'interno del pacchetto java.util.concurrent.lock contenente ampie implementazioni di blocco.

Competenze di sviluppo software richieste

Corsi JavaScript Corsi di base in Java Corsi sulle strutture dei dati
Node.js Corsi Corsi SQL Corsi di sviluppo full stack
Corsi NFT Corsi DevOps Corsi sui Big Data
Corsi React.js Corsi di sicurezza informatica Corsi di cloud computing
Corsi di progettazione di database Corsi di Python Corsi di criptovaluta

Metodo sincronizzato Java

Lo scopo di un metodo sincronizzato Java è bloccare gli oggetti per le risorse condivise. Pertanto, quando i thread invocano un metodo sincronizzato, il metodo ottiene automaticamente il blocco per quell'oggetto e lo rilascia una volta che il thread ha eseguito il proprio lavoro.

Ecco un esempio di metodo sincronizzato Java:

//esempio di metodo sincronizzato con java

tabella di classe{

sync void printTable(int n){//metodo sincronizzato

for(int i=1;i<=5;i++){

System.out.println(n*i);

Tentativo{

Thread.sleep(400);

}catch(Eccezione e){System.out.println(e);}

}

}

}

la classe MyThread1 estende Thread{

Tavoletta;

MyThread1(Tabella t){

questo.t=t;

}

esecuzione vuota pubblica(){

t.printTable(5);

}

}

la classe MyThread2 estende Thread{

Tavoletta;

MyThread2(Tabella t){

questo.t=t;

}

esecuzione vuota pubblica(){

t.printTable(100);

}

}

public class TestSynchronization2{

public static void main(String args[]){

Table obj = new Table();//solo un oggetto

MyThread1 t1=nuovo MyThread1(obj);

MyThread2 t2=nuovo MyThread2(obj);

t1.inizio();

t2.inizio();

}

}

Leggi i nostri articoli popolari relativi allo sviluppo software

Come implementare l'astrazione dei dati in Java? Che cos'è Inner Class in Java? Identificatori Java: definizione, sintassi ed esempi
Comprensione dell'incapsulamento in OOPS con esempi Spiegazione degli argomenti della riga di comando in C Le 10 principali caratteristiche e caratteristiche del cloud computing nel 2022
Polimorfismo in Java: concetti, tipi, caratteristiche ed esempi Pacchetti in Java e come usarli? Tutorial Git per principianti: impara Git da zero

Produzione:

5

10

15

20

25

100

200

300

400

500

Cosa succede senza sincronizzazione?

Ora, diamo un'occhiata al programma precedente senza sincronizzazione (notare l'assenza della parola chiave sincronizzata).

tabella di classe{

void printTable(int n){//metodo non sincronizzato

for(int i=1;i<=5;i++){

System.out.println(n*i);

Tentativo{

Thread.sleep(400);

}catch(Eccezione e){System.out.println(e);}

}

}

}

la classe MyThread1 estende Thread{

Tavoletta;

MyThread1(Tabella t){

questo.t=t;

}

esecuzione vuota pubblica(){

t.printTable(5);

}

}

la classe MyThread2 estende Thread{

Tavoletta;

MyThread2(Tabella t){

questo.t=t;

}

esecuzione vuota pubblica(){

t.printTable(100);

}

}

classe TestSynchronization1{

public static void main(String args[]){

Table obj = new Table();//solo un oggetto

MyThread1 t1=nuovo MyThread1(obj);

MyThread2 t2=nuovo MyThread2(obj);

t1.inizio();

t2.inizio();

}

}

Produzione:

5

100

10

200

15

300

20

400

25

500

Come puoi vedere, l'output è incoerente senza sincronizzazione.

Tipi di sincronizzazione in Java

Per rispondere a cos'è la sincronizzazione dei thread in Java , sono disponibili due tipi di sincronizzazione: la sincronizzazione dei thread e la sincronizzazione dei processi.

Capiamo cosa significa ciascuno.

Sincronizzazione dei thread: quando più thread tentano di accedere a una risorsa condivisa, è necessario assicurarsi che la risorsa venga utilizzata da un solo thread alla volta. La sincronizzazione dei thread è il processo che consente a un solo thread di utilizzare la risorsa condivisa quando più thread tentano di utilizzare la risorsa contemporaneamente.

Sincronizzazione dei processi: si riferisce all'esecuzione simultanea di più processi per raggiungere uno stato in cui i processi si impegnano a un ordine di esecuzione appropriato. La sincronizzazione dei processi è necessaria quando due o più processi cooperano e l'esecuzione di un processo influisce sull'altro. Pertanto, la sincronizzazione dei processi elimina la possibilità di output imprecisi e garantisce il corretto ordine di esecuzione.

Metodi di sincronizzazione in Java

In generale, ci sono quattro metodi di sincronizzazione in Java:

  • Metodi statici sincronizzati
  • Metodi di istanza sincronizzati
  • Blocco sincronizzato all'interno di metodi statici
  • Blocco sincronizzato all'interno dei metodi di istanza

Diamo un'occhiata a ciascun metodo di sincronizzazione Java in modo più dettagliato.

Metodi statici sincronizzati

Qui, utilizziamo la parola chiave sincronizzata per contrassegnare i metodi statici in Java. Ecco un esempio di metodo statico sincronizzato con Java:

MyStaticCounter pubblico statico {

conteggio int statico privato = 0;

public statico sincronizzato void incremento (valore int) {

conteggio += valore;

}

}

Metodi di istanza sincronizzati

Quando si utilizza un blocco sincronizzato con metodi di istanza, ogni oggetto ha il proprio metodo sincronizzato. Ogni oggetto può avere un solo thread che può essere eseguito all'interno di un metodo. Se sono presenti più oggetti, un singolo thread può essere eseguito per ogni oggetto all'interno del blocco.

classe pubblica MyCounter {

conteggio int privato = 0;

incremento del vuoto sincronizzato pubblico (valore int) {

this.count += valore;

}

decremento vuoto sincronizzato pubblico (valore int) {

questo.conteggio -= valore;

}

}

Blocco sincronizzato all'interno di metodi statici

Di seguito è riportato un esempio in cui utilizziamo un blocco sincronizzato all'interno di un metodo statico:

classe pubblica MyClass {

stampa vuota statica pubblica (messaggio stringa) {

sincronizzato(MyClass.class) {

log.writeln(messaggio);

}

}

}

Blocco sincronizzato all'interno dei metodi di istanza

Invece di sincronizzare l'intero metodo, possiamo utilizzare sincronizzato su un blocco specifico all'interno del metodo. Di seguito è riportato un esempio di un blocco di codice sincronizzato all'interno di un metodo non sincronizzato:

incremento vuoto pubblico (valore int) {

sincronizzato(questo) {

this.count += valore;

}

}

Necessità di sincronizzazione in Java

Ora che sai cos'è la sincronizzazione in Java , potresti chiederti perché lo usiamo in primo luogo.

La parola chiave sincronizzata Java fornisce funzionalità essenziali per la programmazione simultanea. Ecco come aiuta la sincronizzazione in Java:

  • La sincronizzazione Java fornisce la funzione di blocco per eliminare qualsiasi race condition tra i thread e garantire l'accesso mutuamente esclusivo alla risorsa condivisa.
  • Il blocco sincronizzato Java fornisce sia le funzioni di blocco che di sblocco. Pertanto, un thread deve acquisire il blocco prima di immettere un metodo o un blocco sincronizzato.
  • La parola chiave sincronizzata impedisce il riordino delle istruzioni del programma da parte del compilatore.

Conclusione

Riassumendo, la sincronizzazione in Java assicura che un solo thread alla volta possa accedere alla risorsa condivisa. Possiamo sincronizzare un blocco o un metodo utilizzando la parola chiave sincronizzata Java. Quando un thread vuole entrare in un blocco sincronizzato, deve acquisire un blocco e, dopo aver lasciato il blocco, il thread rilascia il blocco. Possiamo usare la parola chiave sincronizzata sia con i metodi che all'interno del blocco di un metodo.

Vuoi imparare i concetti fondamentali in Java? Il corso upGrad Executive Post Graduate in Software Development - Specializzazione in Full Stack Development è un programma online di 7 settimane per principianti che vogliono esplorare le carriere nello sviluppo di software. Partecipa a lezioni dal vivo e interattive, sessioni di pratica e oltre 35 ore di contenuti forniti dai leader del settore per ottenere un certificato di completamento da upGrad.

Iscriviti oggi per usufruire dei vantaggi esclusivi di upGrad del supporto per gli studenti 24 ore su 24, 7 giorni su 7 e del networking del settore!

Perché utilizziamo sincronizzato in Java?

La parola chiave sincronizzata in Java garantisce che un solo thread alla volta possa accedere alle risorse condivise. È utile quando i programmi Java multithread tentano di accedere alla stessa risorsa e producono risultati imprecisi.

Come viene implementata la sincronizzazione in Java?

Java implementa la sincronizzazione utilizzando il concetto di monitor con un solo thread che possiede un monitor in un dato momento. Quando un thread acquisisce un blocco, ottiene l'accesso al monitor e tutti gli altri thread che tentano di accedere al monitor bloccato rimangono bloccati finché il primo thread non lascia il monitor.

Che cos'è un deadlock in Java?

Il deadlock Java si verifica quando un thread è in attesa di un blocco oggetto, ma un altro thread lo acquisisce e il secondo thread è in attesa di un blocco oggetto acquisito dal primo. Pertanto, entrambi i thread attendono l'un l'altro per rilasciare il blocco, determinando un deadlock.