
목차
- 데드락이란
- 데드락의 발생조건
- 데드락을 방지하기
데드락(DeadLock)은 시스템 자원에 대한 요구가 뒤엉킨 상태이다.
데드락이 발생하기 위해서는 아래 4가지 조건이 모두 만족되어야 한다. 이 조건들은
Coffman의 조건으로도 알려져 있다.
1.상호 배제
2.점유 및 대기
3.비선점
4.순환 대기
상호 배제는 특정 자원이 한 번에 하나의 프로세스만 사용할 수 있도록 하는 메커니즘이다.
자원의 일관성과 무결성을 유지하기 위해 필수적이다.public class PrintingTask implements Runnable{
private final Printer printer;
private final String message;
public PrintingTask(Printer printer, String message) {
this.printer = printer;
this.message = message;
}
@Override
public void run() {
printer.print(message);
}
public static void main(String[] args) {
Printer printer = new Printer();
Thread t1 = new Thread(new PrintingTask(printer, "Document 1"));
Thread t2 = new Thread(new PrintingTask(printer, "Document 2"));
t1.start();
t2.start();
}
}
class Printer {
private final Object lock = new Object();
public void print(String message) {
synchronized (lock) {
System.out.println("Printing: " + message);
try {
Thread.sleep(1000); // Simulate the time taken to print
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Done printing: " + message);
}
}
}

데드락이 발생하기 위한 조건 중 하나인 점유 및 대기는 자원을 점유한 상태에서 추가 자원을 기다리는 상황을 의미한다.
점유(Hold): 프로세스가 하나 이상의 자원을 점유하고 있는 상태대기(Wait): 이미 점유한 자원을 해제하지 않은 상태에서, 추가적인 자원을 요청하고 대기하는 상태
자원의 점유 : 프로세스가 현재 특정 자원을 접유하고 있어야 한다. -> 점유 자원은 다른 프로세스가 접근불가추가 자원의 요청 : 프로세스가 추가적인 자원을 요청한다. -> 이미 점유하고 있는 자원은 해제하지 않은상태대기 상태 : 요청한 자원이 사용 중이기 때문에, 프로세스는 해당 자원이 해제될 때가지 대기한다.public class DeadlockExample {
private static final Object resource1 = new Object();
private static final Object resource2 = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (resource1) {
System.out.println("Thread 1: Holding resource 1...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1: Waiting for resource 2...");
synchronized (resource2) {
System.out.println("Thread 1: Acquired resource 2.");
}
}
});
Thread t2 = new Thread(() -> {
synchronized (resource2) {
System.out.println("Thread 2: Holding resource 2...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 2: Waiting for resource 1...");
synchronized (resource1) {
System.out.println("Thread 2: Acquired resource 1.");
}
}
});
t1.start();
t2.start();
}
}

비선점은 OS와 리소스 관리에서 사용하는 개념으로, 자원을 한 번 할당받은 프로세스는 그 자원을 스스로 해제할 때까지 다른 프로세스가 강제로 뺴앗을 수 없음을 의미한다.
public class NonPreemptiveDeadlockExample {
private static final Object resource1 = new Object();
private static final Object resource2 = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (resource1) {
System.out.println("Thread 1: Holding resource 1...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1: Waiting for resource 2...");
synchronized (resource2) {
System.out.println("Thread 1: Acquired resource 2.");
}
}
});
Thread t2 = new Thread(() -> {
synchronized (resource2) {
System.out.println("Thread 2: Holding resource 2...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 2: Waiting for resource 1...");
synchronized (resource1) {
System.out.println("Thread 2: Acquired resource 1.");
}
}
});
t1.start();
t2.start();
}
}

프로세스들이 순환 형태로 자원을 기다리는 상태를 말한다.
public class CircularWaitExample {
private static final Object resource1 = new Object();
private static final Object resource2 = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
synchronized (resource1) {
System.out.println("Thread 1: Holding resource 1...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1: Waiting for resource 2...");
synchronized (resource2) {
System.out.println("Thread 1: Acquired resource 2.");
}
}
});
Thread t2 = new Thread(() -> {
synchronized (resource2) {
System.out.println("Thread 2: Holding resource 2...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 2: Waiting for resource 1...");
synchronized (resource1) {
System.out.println("Thread 2: Acquired resource 1.");
}
}
});
t1.start();
t2.start();
}
}

데드락을 예방하거나 회피하는 방법은 시스템의 안정성을 유지하고 자원 관리를 효율적으로 수행하기 위해 매우 중요하다.
데드락을 방지하기 위한 전략은예방(Prevention),회피(Avoidance),탐지 및 복구(Detection and Recovery)가 있다.
상호배제 조건 제거점유 및 대기 조건 제거비선점 조건 제거순환대기 조건 제거은행가 알고리즘(Banker's Algorithm)이 있다.안전 상태(Safe State) : 시스템이 모든 프로세스에 대해 자원을 할당할 수 있는 순서가 존재하는 상태안전 순서(Safe Sequence) : 프로세스들이 데드락 없이 자원을 할당받아 실행될 수 있는 순서자원 할당 그래프와 웨이트-포 그래프를 사용한다.프로세스 종료 와 자원 선점 이다.