[c#] C# 스레드 데드락
C#에서 멀티스레딩은 애플리케이션의 성능을 향상시키고 복잡한 작업을 보다 효율적으로 처리할 수 있게 도와줍니다. 그러나, 잘못된 스레드 동기화 구현으로 인해 데드락(deadlock)이 발생할 수 있습니다. 데드락은 두 개 이상의 스레드가 서로 상대방이 가진 자원을 기다리며 무한정으로 대기하는 상황을 말합니다.
데드락 예시
아래는 간단한 예제 코드를 통해 C#의 데드락 상황을 이해해 봅시다.
using System;
using System.Threading;
class Program
{
static object lockA = new object();
static object lockB = new object();
static void Main()
{
Thread thread1 = new Thread(() =>
{
lock (lockA)
{
Thread.Sleep(1000);
lock (lockB)
{
Console.WriteLine("Thread 1: Got lockB");
}
}
});
Thread thread2 = new Thread(() =>
{
lock (lockB)
{
lock (lockA)
{
Console.WriteLine("Thread 2: Got lockA");
}
}
});
thread1.Start();
thread2.Start();
}
}
위의 코드는 lockA
와 lockB
두 가지의 락을 사용하여 서로 다른 스레드 간에 경합을 유발합니다. thread1
은 lockA
를 획득하고 lockB
를 얻으려하고, 반면 thread2
는 lockB
를 획득하고 lockA
를 얻으려 합니다.
데드락 방지와 해결
데드락을 방지하고 해결하기 위해서는 스레드 동기화에 신중함이 필요합니다. 대부분의 데드락은 상호배제, 점유 대기, 순환 대기, 선점 불가 등의 조건 중에 하나 이상이 충족될 때 발생합니다. 따라서, 이러한 조건들을 만족시키지 않도록 프로그래밍 하는 것이 중요합니다.
데드락을 방지하고 해결하는 방법에는 다음과 같은 것들이 있습니다:
- 락을 획득하는 순서를 고정하는 방법
- 락을 짧은 시간 동안만 보유하도록 하는 방법
Monitor.TryEnter
또는Monitor.Enter
와Monitor.Exit
메소드를 사용하여 안전하게 락을 해제하는 방법
또한, C#에서는 Task
또는 async/await
같은 비동기 프로그래밍 기법을 사용하여 락을 획득하지 않고도 비동기적으로 작업을 수행할 수 있습니다.
결론
C#에서 데드락은 올바른 스레드 동기화를 통해 방지할 수 있습니다. 적절한 동기화 기법과 스레드 안전성을 유지하는 것이 중요하며, 비동기 프로그래밍 기법을 사용하여 락을 회피하는 방법 또한 고려해야 합니다.
참고자료:
- https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/threading/deadlocks