데드락은 두 개 이상의 프로세스가 서로 상대방이 점유하고 있는 자원을 기다리며 무한정 대기하는 상태를 말합니다. 즉, 각 프로세스가 자신이 필요로 하는 자원을 얻기 위해 다른 프로세스가 해제되기를 기다리는데, 다른 프로세스 역시 자원을 해제하지 못하고 있는 상황입니다. 이런 상황에서는 프로세스들이 계속 대기 상태에 빠지게 되어 더 이상 진행할 수 없게 됩니다.
1. 소스
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
private static readonly object lockA = new object();
private static readonly object lockB = new object();
static async Task Main(string[] args)
{
var task1 = Task.Run(() => TaskA());
var task2 = Task.Run(() => TaskB());
await Task.WhenAll(task1, task2);
Console.WriteLine("Tasks completed");
}
private static void TaskA()
{
lock (lockA)
{
Console.WriteLine("TaskA acquired lockA");
Thread.Sleep(100); // Simulate work
lock (lockB)
{
Console.WriteLine("TaskA acquired lockB");
// Simulate work
}
}
}
private static void TaskB()
{
lock (lockB)
{
Console.WriteLine("TaskB acquired lockB");
Thread.Sleep(100); // Simulate work
lock (lockA)
{
Console.WriteLine("TaskB acquired lockA");
// Simulate work
}
}
}
}
2. 결과
TaskB acquired lockB
TaskA acquired lockA
3. 분석
이 코드는 두 개의 작업(TaskA와 TaskB)이 서로 다른 순서로 두 개의 잠금(lockA와 lockB)을 얻으려고 할 때 데드락(교착 상태)이 발생할 수 있음을 보여줍니다.
TaskA는 먼저 lockA를 얻은 다음 lockB를 얻으려고 합니다. 반면에 TaskB는 먼저 lockB를 얻은 다음 lockA를 얻으려고 합니다.
이렇게 서로 다른 순서로 잠금을 시도하기 때문에, TaskA는 lockA를 잡고 lockB를 기다리는 상황에 놓이고, 동시에 TaskB는 lockB를 잡고 lockA를 기다리는 상황에 놓입니다. 이로 인해 두 작업 모두 더 이상 진행할 수 없는 교착 상태에 빠지게 됩니다.
실제로 이 코드를 실행하면, 프로그램이 데드락에 빠져 "Tasks completed" 메시지가 출력되지 않고, 무한히 대기 상태에 빠져 있는 것을 볼 수 있습니다. 이를 통해 데드락 상황이 발생했음을 확인할 수 있습니다.
데드락을 피하기 위해서는 모든 스레드가 동일한 순서로 잠금을 얻도록 코드를 작성해야 합니다. 또는, Mutex와 같은 고급 동기화 메커니즘을 사용하는 것이 좋습니다.
'Language > C#' 카테고리의 다른 글
[C#] 이진 탐색 (Binary search) vs 균형 이진 트리 (Balanced Binary Search Tree) 속도 비교 (0) | 2024.06.14 |
---|---|
[C#] 파일 생성 일자 비교 후 이전 날짜 파일 삭제하기 (0) | 2023.03.14 |
인터넷 또는 제한 영역에 있거나 파일에 웹 표시가 있으므로 처리할 수..... (1) | 2023.02.02 |