Thread 동기화 관련하여 네이버 지식인의 답변 내용을 발췌.
질문의 요점은 비동기식 프로그램에서 개발자가 원하는 동기화를 하기 위해 C#에서는 어떠한 것이 필요한지에 대한 물음인 것 같네요.
원하시는 답변은 방법3에 있는데 방법1과 방법2도 한번 살펴보세요.
방법 1. lock 사용
먼저 lock키워드를 사용하는 쉬운 방법이 있습니다.
어떠한 메소드 내에서 자원 경쟁(race condition)을 해야 하는 부분이라고 생각하시면 다음과 같이 하면 여러 쓰레드(혹은 job 객체)에서 먼저 진입해서 빠져 나오기 전까지 대기(wait)하다가 진입한 곳에서 빠져 나오면 진입하게 됩니다.
public void Foo()
{
lock (경쟁자원)
{
//to do
}
}
단, 경쟁 자원이 class기반의 개체여야 한다는 제약 조건이 있습니다. 대부분 lock(this)로 해서 경쟁 자원이 있는 class의 경쟁해야 하는 경우에 쉽게 표현할 수 있습니다.
쉬운 반면 자원 해제를 예측한 시간 안에 하지 못한다면 전체 성능을 저하시킬 수 있는 문제를 갖고 있습니다.
방법 2. Monotor 사용
lock 키워드와 같은 목적으로 사용할 수 있습니다.
자원 경쟁을 해야 하는 개체가 x라 할 때 다음과 같이 사용(진입)하기 위해 System.Threading.Monitor.Enter메소드를 사용하고 사용이 끝나고 나서 System.Threading.Monitor.Exit을 호출하시면 됩니다.
물론 using System.Threading;을 기재하시면 Monitor.Enter와 Monitor.Exit만 기재해도 되겠죠.
System.Object obj = (System.Object)x;
System.Threading.Monitor.Enter(obj);
try
{
//to do
}
finally
{
System.Threading.Monitor.Exit(obj);
}
MSDN에 보면 Monitor보다는 lock을 권고하고 있습니다.
Monitor에 대한 자세한 사항을 보시고 싶으면Monitor Synchronization 기술 샘플을 참고하십시요.
방법 3. 아마도 질문하신 분이 원하는 답변이 될 듯
오해의 소지를 없애기 위해 MSDN을 발췌하겠습니다.
lock 또는 monitor를 사용하면 스레드가 중요한 부분을 차지하는 코드 블록이 동시에 실행되지 않도록 방지할 수 있지만 이러한 구문을 사용하면 한 스레드가 다른 스레드에 이벤트를 전달할 수 없습니다. 이 문제를 해결하기 위해서는 스레드를 활성화하거나 일시 중단하는 데 사용할 수 있고 신호를 받은 상태 및 신호를 받지 않은 상태 중 한 가지 상태가 지정되는 개체인 동기화 이벤트가 필요합니다. 스레드를 일시 중단하려면 신호를 받지 않은 상태의 동기화 이벤트에서 스레드를 대기시키고, 스레드를 활성화하려면 신호를 받은 상태로 이벤트 상태를 변경합니다. 이미 신호를 받은 상태의 이벤트에서 스레드를 대기시키려고 하면 스레드가 지연 시간 없이 계속 실행됩니다.
동기화 이벤트에는 AutoResetEvent와 ManualResetEvent라는 두 가지 종류가 있습니다. 이 둘 사이의 유일한 차이는 AutoResetEvent의 경우 스레드를 활성화할 때마다 신호를 받은 상태에서 신호를 받지 않은 상태로 자동으로 변경된다는 점입니다. 반대로, ManualResetEvent를 사용하면 신호를 받은 상태를 통해 스레드를 그 수에 상관없이 활성화할 수 있고 해당Reset 메서드를 호출한 경우에만 신호를 받지 않은 상태로 되돌릴 수 있습니다.
WaitOne,WaitAny 또는 WaitAll 같은 대기 메서드 중 하나를 호출하여 이벤트에 대해 스레드가 대기하도록 할 수 있습니다. WaitHandle..::.WaitOne()은 단일 이벤트가 신호를 받을 때까지 스레드를 대기시키고, WaitHandle..::.WaitAny()는 하나 이상의 지정된 이벤트가 신호를 받을 때까지 스레드를 차단하며,WaitHandle..::.WaitAll()()()은 지정된 모든 이벤트가 신호를 받을 때까지 스레드를 차단합니다. 이벤트는 해당 Set 메서드가 호출되면 신호를 받은 상태로 변경됩니다.
다음 예제에서는 wait함수를 사용하여 스레드를 만들고 시작합니다. 새 스레드는 WaitOne 메서드를 사용하여 이벤트에서 대기합니다. wait 함수를 실행하는 기본 스레드를 통해 이벤트가 신호를 받은 상태가 될 때까지 이 스레드는 일시 중단됩니다. 이벤트가 신호를 받은 상태가 되면 보조 스레드가 반환됩니다. 이 경우 이벤트는 스레드 하나의 활성화에만 사용되므로 AutoResetEvent 또는 :TrackManualResetEvent 클래스를 사용할 수 있습니다.
using System.Threading;
class ThreadingExample
{
static AutoResetEvent autoEvent;
static void DoWork()
{
Console.WriteLine(" worker thread started, now waiting on event...");
autoEvent.WaitOne();
Console.WriteLine(" worker thread reactivated, now exiting...");
}
static void Main()
{
autoEvent = new AutoResetEvent(false);
Console.WriteLine("main thread starting worker thread...");
Thread t = new Thread(DoWork);
t.Start();
Console.WriteLine("main thread sleeping for 1 second...");
Thread.Sleep(1000);
Console.WriteLine("main thread signaling worker thread...");
autoEvent.Set();
}
}
그리고, race condition문제에 대한 criticalsection을 결정을 하는데 있어WatiForSingleObject도 Win32API에서도 소극적인 처신이니 Win32API의 동기화 기법을 다시 한 번 확인해 보시길 권합니다.
그밖의 자료들..
Thread 란?
http://leeom.blog.me/70095295108
c# 스레드 강좌
스레드 간 컨트롤 접근과 스레드 동기화 1탄
http://ljh0707.blog.me/10017188903
C# 초보입니다. Win32에 있는 WaitForSingleObject ????
윈폰7 관련 링크
초보자들을 위한 동영상 강의
http://channel9.msdn.com/Series/Windows-Phone-7-Development-for-Absolute-Beginners?page=2
c# 초보자를 위한 레퍼런스 모음
http://cafe.naver.com/ongameserver.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=3334
추천책
C# and the .NET Platform
책비교 사이트
참고블로그
http://blog.naver.com/saltynut
http://www.hoons.kr/default.aspx
.net 표준개발 가이드
http://www.microsoft.com/korea/MSDN/netframework/technologyinfo/overview/netdevelopmentguid.aspx
C# 4.0 소개
C# 개발자 블로그 - 다양한 경험 공유
'프로그래밍 > .Net' 카테고리의 다른 글
Tick Count 가져오기 (0) | 2014.01.17 |
---|---|
WaitHandles 사용 (0) | 2014.01.17 |
[C#] Internal 지정자 (0) | 2014.01.17 |
LoaderLock 관리 디버깅 도우미 문제 (0) | 2014.01.17 |
Handle hWND (0) | 2014.01.17 |