아래와 같이 2개의 Lock이 존재하며,
2개의 쓰레드가 Lock에 접근하는 경우 DeadLock이 발생했다.
namespace SeverCore
{
class SessionManager
{
static object _lock = new object();
public static void TestSession()
{
lock (_lock)
{
}
}
public static void Test()
{
lock (_lock)
{
UserManager.TestUser();
}
}
}
class UserManager
{
static object _lock = new object();
public static void Test()
{
lock (_lock)
{
SessionManager.TestSession();
}
}
public static void TestUser()
{
lock (_lock)
{
}
}
}
class Program
{
static int number = 0;
static object _obj = new object();
static void Thread_1()
{
for (int i = 0; i < 10000; i++)
{
SessionManager.Test();
}
}
static void Thread_2()
{
for (int i = 0; i < 10000; i++)
{
UserManager.Test();
}
}
static void Main(string[] args)
{
Task t1 = new Task(Thread_1);
Task t2 = new Task(Thread_2);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
Console.WriteLine(number);
}
}
}
이 상황을 어떻게 해결할까?
Monitor.TryEnter() 키워드를 이용해서 일정시간동안 lock을 획득하지 못했으면 포기하도록 할 수 있다.
하지만 이와 같은 경우 결국 lock 구조에 문제가 있다는 것이니 좋은 해결책은 아닐 수 있다.
Monitor.TryEnter();
Thread.Sleep 키워드를 이용해 해당 명령어들의 실행을 어긋나도록 만드는 것도 해결책이 될 수 있다.
static void Main(string[] args)
{
Task t1 = new Task(Thread_1);
Task t2 = new Task(Thread_2);
t1.Start();
t2.Start();
Thread.Sleep(100);
Task.WaitAll(t1, t2);
Console.WriteLine(number);
}
하지만 보통은 crash가 난 다음에 고치는 경우가 흔하다.
DeadLock은 굉장히 까다롭기 때문에!