Concorrenza Java - Deadlock
Deadlock descrive una situazione in cui due o più thread sono bloccati per sempre, in attesa l'uno dell'altro. Il deadlock si verifica quando più thread richiedono gli stessi blocchi ma li ottengono in un ordine diverso. Un programma multithread Java potrebbe soffrire della condizione di deadlock perché il filesynchronizedla parola chiave fa sì che il thread in esecuzione si blocchi durante l'attesa del blocco, o monitoraggio, associato all'oggetto specificato. Ecco un esempio.
Esempio
public class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
T2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 2...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
Quando compili ed esegui il programma sopra, trovi una situazione di deadlock e il seguente è l'output prodotto dal programma -
Produzione
Thread 1: Holding lock 1...
Thread 2: Holding lock 2...
Thread 1: Waiting for lock 2...
Thread 2: Waiting for lock 1...
Il programma sopra si bloccherà per sempre perché nessuno dei thread è in posizione per procedere e aspetta che l'altro rilasci il blocco, quindi puoi uscire dal programma premendo CTRL + C.
Esempio di soluzione deadlock
Cambiamo l'ordine del blocco e l'esecuzione dello stesso programma per vedere se entrambi i thread si aspettano ancora l'uno per l'altro -
Esempio
public class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
T2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
Quindi la semplice modifica dell'ordine dei blocchi impedisce al programma di entrare in una situazione di deadlock e si completa con il seguente risultato:
Produzione
Thread 1: Holding lock 1...
Thread 1: Waiting for lock 2...
Thread 1: Holding lock 1 & 2...
Thread 2: Holding lock 1...
Thread 2: Waiting for lock 2...
Thread 2: Holding lock 1 & 2...
L'esempio sopra è solo per chiarire il concetto, tuttavia, è un concetto complesso e dovresti approfondirlo prima di sviluppare le tue applicazioni per affrontare situazioni di deadlock.