지금까지 우리는 Critical Section을 구현하는 대표적인 3가지 방법에 대해 알아 보았다.
이번 시간에는 특수한 상황에서 Critical Section을 구현하는 방법에 대해 알아보자.
특수한 상황이란 다음과 같다.
'어떤 던전을 완료하면 보상으로 5개의 아이템을 준다. 5개의 아이템은 거의 고정되어있다. 근데 정말 드물게 이벤트로 1~2개의 아이템을 추가로 준다.'
아이템 세트를 수정한다는 것은 메모리에 접근해서 데이터를 수정한다는 뜻이다. 이 작업을 하는 동안에 다른 쓰레드에서 접근하면 안되니까 Lock을 걸어주긴 해야한다.
그치만 데이터를 수정하는 작업이 일어날 확률은 정말 드물다는 것이 문제이다.
참고사항) 컨텐츠와 DB는 따라 생각하자.
최종적으로 아이템이 DB에 저장되는 것은 맞지만,
그와는 별개로 DB 부하 때문에 유저 정보를 매 번마다 DB에서 Load 할 수는 없습니다.
따라서 보통 유저가 게임에 접속하는 순간,
DB에서 해당 유저의 모든 정보(아이템, 스킬, 업적 등)를 싹 긁어와 서버 메모리에서 따로 관리하게 됩니다.
이때 사용하는 것이 ReaderWriterLock 이다.
항상 그래왔듯이 화장실로 비유를 들자면, 공중 화장실을 만들어서 평상 시에는 사람들(쓰레드)들이 공동으로 볼 일을 볼 수 있게 해주지만,
아주 예외적인 손님(VIP)이 올 때는 그 사람만 볼 일을 볼 수 있게 만들어주는 것이다.
코드를 살펴보자.
class Reward { }
static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
static Reward GetRewardById(int id)
{
_lock.EnterReadLock(); // 마치 Lock이 없는 것 처럼...
_lock.ExitReadLock();
return null;
}
static Reward AddRewardById(int id)
{
_lock.EnterWriteLock();
_lock.ExitWriteLock();
return null;
}
ReaderWriterLockSlim은 ReaderWriterLock의 개정된 버전이다. 구 버전은 굳이 사용할 필요가 없다.
GetRewardById 에서는 ReadLock을 사용하면 Mutal Exclusive(상호배제)가 성립이 안되지만
AddRewardById 처럼 WriteLock을 사용하면 Mutal Exclusive가 성립이 된다.