Java Concurrency - Deadlock
Deadlock menggambarkan situasi di mana dua atau lebih utas diblokir selamanya, menunggu satu sama lain. Kebuntuan terjadi ketika beberapa utas membutuhkan kunci yang sama tetapi mendapatkannya dalam urutan yang berbeda. Program multithread Java mungkin mengalami kondisi kebuntuan karenasynchronizedkata kunci menyebabkan utas pelaksana untuk memblokir sambil menunggu kunci, atau monitor, terkait dengan objek yang ditentukan. Berikut ini contohnya.
Contoh
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...");
}
}
}
}
}
Ketika Anda mengkompilasi dan menjalankan program di atas, Anda menemukan situasi kebuntuan dan berikut adalah keluaran yang dihasilkan oleh program -
Keluaran
Thread 1: Holding lock 1...
Thread 2: Holding lock 2...
Thread 1: Waiting for lock 2...
Thread 2: Waiting for lock 1...
Program di atas akan hang selamanya karena tak satu pun dari utas dalam posisi untuk melanjutkan dan menunggu satu sama lain untuk melepaskan kunci, sehingga Anda dapat keluar dari program dengan menekan CTRL + C.
Contoh Solusi Kebuntuan
Mari kita ubah urutan kunci dan jalankan program yang sama untuk melihat apakah kedua utas masih menunggu satu sama lain -
Contoh
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...");
}
}
}
}
}
Jadi hanya dengan mengubah urutan kunci mencegah program mengalami situasi kebuntuan dan selesai dengan hasil sebagai berikut -
Keluaran
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...
Contoh di atas adalah untuk memperjelas konsepnya, namun, ini adalah konsep yang kompleks dan Anda harus mendalami lebih dalam sebelum mengembangkan aplikasi untuk menghadapi situasi kebuntuan.