C#

Lock 구현 훑어내리기 + ReaderWriterLock 기초

monstro 2024. 12. 4. 17:04
728x90
반응형

1) 일반적인 lock

가장 먼저 알아볼 Lock 구현은 일반적인 lock 키워드를 통한 lock 입니다.

사용할 수 있는 방식은 다음과 같습니다.

static object _lock = new object();

static void Main(string[] args)
{
    lock (_lock)
    { 
    
    }
}

 

object 타입의 _lock 변수를 사용하며

lock의 경우 내부적으로 Monitor가 동작합니다.

 

2) SpinLock

다음으로는 SpinLock을 통한 Lock 구현입니다.

SpinLock을 통해 Lock은 무한히 대기하며 자원의 점유가 풀리기를 기다립니다.

사용할 수 있는 방식은 다음과 같습니다.

class Program
{
    // C# API - SpinLock : 이때의 SpinLock은 너무 오래 기다린다 싶으면 return yield로 자원독점을 양보한다
    static SpinLock _lock2 = new SpinLock();

    static void Main(string[] args)
    {

        bool _lockTaken = false;
        try
        {
            _lock2.Enter(ref _lockTaken);
        }
        finally 
        {
            if (_lockTaken)
                _lock2.Exit();
        }
    }
}

 

사용예시의 SpinLockC#에서 제공하는 API의 SpinLock으로서 내부적으로

대기시간이 너무 길어지면 yield return을 통해 동작가능한 스레드에게 자원에 대한 권한을 넘겨줍니다.

이때 SpinLock API의 경우 불리언 값을 통해 Lock 여부를 판단합니다.

 

Lock과 SpinLock의 경우 가장 큰 공통점은 두 Lock 모두 상호배타를 모토로 동작한다는 것입니다.

자원에 대해 점유하는 스레드외의 어떤 스레드도 접근하지 못하게 하는 것이 가장 큰 특징입니다.

 

하지만 어떤 경우에는 자원의 값을 가져오기만 하는 경우도 있습니다.

값을 새로 쓰지 않는 이상 가져오는 것은 큰 문제가 되지 않습니다.

그리고 이런 경우를 위해 사용할 수 있는 Lock이 존재합니다.

 

3) ReaderWriterLock

static ReaderWriterLockSlim _lock3 = new ReaderWriterLockSlim();

static void GetData()
{
    _lock3.EnterReadLock();

    _lock3.ExitReadLock();
}

static void SetData()
{
    _lock3.EnterWriteLock();

    _lock3.ExitWriteLock();
}

 

ReaderWriterLock 같은 경우 자원에 대해 값을 가져오는 것에 대해서는 따로 Lock을 걸지 않고

대신 값을 새로 쓰는 경우에 대해서는 Lock을 적용합니다.

기존의 Lock에 비해 훨씬 유연한 처리가 가능합니다.

 

읽는 경우에 Lock된 자원에 들어가기 위해서는 EnterReadLock 함수를 사용하고,

나가기 위해서는 ExtiReadLock 함수를 사용합니다.

 

쓰는 경우에 Lock된 자원에 들어가기 위해서는 EnterWriteLock 함수를 사용하고,

나가기 위해서는 ExitWriteLock 함수를 사용합니다. 

728x90
반응형

'C#' 카테고리의 다른 글

Thread Local Storage  (0) 2024.12.09
ReaderWriterLock 구현  (0) 2024.12.09
Event를 통한 Lock 구현  (0) 2024.12.04
Context Switching  (0) 2024.12.04
SpinLock  (0) 2024.12.04