Concurrence Java - Blocage
Le blocage décrit une situation dans laquelle deux ou plusieurs threads sont bloqués pour toujours, en attente l'un de l'autre. Un blocage se produit lorsque plusieurs threads ont besoin des mêmes verrous mais les obtiennent dans un ordre différent. Un programme Java multithread peut souffrir de la condition de blocage car lesynchronizedLe mot-clé provoque le blocage du thread en cours d'exécution en attendant le verrou, ou le moniteur, associé à l'objet spécifié. Voici un exemple.
Exemple
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...");
}
}
}
}
}
Lorsque vous compilez et exécutez le programme ci-dessus, vous trouvez une situation de blocage et voici la sortie produite par le programme -
Production
Thread 1: Holding lock 1...
Thread 2: Holding lock 2...
Thread 1: Waiting for lock 2...
Thread 2: Waiting for lock 1...
Le programme ci-dessus se bloquera pour toujours car aucun des threads en position de continuer et n'attendant l'un l'autre pour libérer le verrou, vous pouvez donc sortir du programme en appuyant sur CTRL + C.
Exemple de solution de blocage
Changeons l'ordre du verrou et exécutons le même programme pour voir si les deux threads attendent toujours l'un l'autre -
Exemple
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...");
}
}
}
}
}
Donc, le simple fait de changer l'ordre des verrous empêche le programme d'entrer dans une situation de blocage et se termine avec le résultat suivant -
Production
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'exemple ci-dessus vise simplement à clarifier le concept, cependant, il s'agit d'un concept complexe et vous devez vous y plonger en profondeur avant de développer vos applications pour faire face à des situations de blocage.