C#/C#정리

[C#] Thread 쓰레드 동기화

반나무 2021. 9. 28. 20:14

사용 이유

  1. 멀티 스레드는 실행 순서가 불규칙하다.
  2. 공유 리소스(shared resource)에 대한 스레드의 동기화(synchronization)처리가 되지않았다.

Monitor : 모니터

Enter와 Exit 코드 사이에 위치한 모든 코드는 한 순간에 스레드 하나만 진입해서 실행할 수 있다.

또한 Enter와 Exit 메서드의 인자로 전달하는 값은 반드시 참조형 타입의 인스턴스여야 한다.

private static object lockObj = new object();

Monitor.Enter(lockObj);
try
{
    ~~~
}
finally
{
    Monitor.Exit(lockObj);
}

* Wait(lockObj)  /  Pulse(lockObj)  / PulseAll(lockObj)

Lock : 스레드 락

부가적으로 C#언어에서는 try/finally + Monitor.Enter/Exit 코드와 동일한 역할을 하는 lock예약어를 제공한다.

구문은 바뀌었지만 C#컴파일러에 의해 최종적으로는 코드변환이된다.

대개의 경우 코드가 간결하다는 이유로 lock예약어를 이용한 구문이 더 선호된다.

private static object lockObj = new object();

lock(lockObj)
{
    ~~~
}

Mutex 뮤텍스

프로세스 간에 Locking 할 때, 느려서 프로세스 내에서 할때는 위 1,2 번 방식 사용

// bool값 = 호출 스레드가 뮤텍스의 초기 소유권 가질지
using(Mutex mutex = new Mutex(false, "MuteName"))  
{
mutex.WaitOne(); 
~~~
mutex.ReleaseMutex();
}

//Release 안할 경우 대비해서
if(mutex.WaitOne(1000))
{
~~~
}
else ~~~    // 1초 지나도 취득 안될경우 할 일.

Semaphore 세마포어

여러개. 이것도 프로세스간 사용 가능.

// n = 처음 요청 개수, m= 최대 요청 개수.
private static Semaphore sema = new Semaphore(n, m) 

sema.WaitOne(); // 이 이후 m개만 들어올 수 있음.
sema.Release(m) // m개를 놔줌(or 수행). () 하면 1개 놔

AutoResetEvent

Set 하면, 하나 이상의 대기중 스레드 중 첫번째로 대기 시작한 쓰레드 하나를 진행시킴.

private static AutoResetEvent autoEvt = new AutoResetEvent(false);  // 초기상태 신호 받음 설정 여부.
    
autoEvt.WaitOne();
autoEvt.Set();

ManualResetEvent

위에랑 달리 Set 1회에 모든 대기중 쓰레드 진행시킴.

private static ManualResetEvent manualEvt = new ManualResetEvent(false);

    manualEvt.WaitOne();
    manualEvt.Set();

CountdownEvent

카운트를 1개씩 줄임.

private static CountdownEvent countEvt = new CountdownEvent(5);
    
countEvt.Signal(); 하면 카운트 하나 줄어든다.
countEvt.IsSet() or countEvt.CurrentCount > 0 이런식으로 if문에 넣어서 사용하면 된다.

 

반응형