Java Concurrency - การหยุดชะงัก
Deadlock อธิบายถึงสถานการณ์ที่เธรดสองเธรดขึ้นไปถูกบล็อกตลอดไปโดยรอกันและกัน การหยุดชะงักเกิดขึ้นเมื่อเธรดหลายเธรดต้องการการล็อกเดียวกัน แต่ได้รับในลำดับที่ต่างกัน โปรแกรมมัลติเธรด Java อาจได้รับผลกระทบจากสภาวะชะงักงันเนื่องจากไฟล์synchronizedคีย์เวิร์ดทำให้เธรดการเรียกใช้บล็อกขณะรอการล็อกหรือมอนิเตอร์ที่เชื่อมโยงกับอ็อบเจ็กต์ที่ระบุ นี่คือตัวอย่าง
ตัวอย่าง
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...");
}
}
}
}
}
เมื่อคุณคอมไพล์และรันโปรแกรมข้างต้นคุณจะพบสถานการณ์ชะงักงันและต่อไปนี้คือผลลัพธ์ที่สร้างโดยโปรแกรม -
เอาต์พุต
Thread 1: Holding lock 1...
Thread 2: Holding lock 2...
Thread 1: Waiting for lock 2...
Thread 2: Waiting for lock 1...
โปรแกรมด้านบนจะหยุดทำงานตลอดไปเนื่องจากเธรดทั้งสองไม่อยู่ในตำแหน่งที่จะดำเนินการต่อและรอให้กันและกันคลายล็อกคุณจึงสามารถออกจากโปรแกรมได้โดยกด CTRL + C
ตัวอย่างโซลูชัน Deadlock
มาเปลี่ยนลำดับการล็อกและรันโปรแกรมเดียวกันเพื่อดูว่าเธรดทั้งสองยังรอกันอยู่หรือไม่ -
ตัวอย่าง
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...");
}
}
}
}
}
ดังนั้นการเปลี่ยนลำดับของการล็อกจะป้องกันไม่ให้โปรแกรมเข้าสู่สถานการณ์ชะงักงันและดำเนินการตามผลลัพธ์ต่อไปนี้ -
เอาต์พุต
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...
ตัวอย่างข้างต้นเป็นเพียงการทำให้แนวคิดชัดเจน แต่เป็นแนวคิดที่ซับซ้อนและคุณควรเจาะลึกลงไปก่อนที่จะพัฒนาแอปพลิเคชันของคุณเพื่อรับมือกับสถานการณ์การชะงัก