타사 솔루션에서 데이터를 받아 데이터베이스에 저장 한 다음 다른 타사 솔루션에서 사용할 데이터를 조정하는 소프트웨어 업데이트를 작성하는 중급 개발자입니다. 우리의 소프트웨어는 Windows 서비스로 실행됩니다.
이전 버전의 코드를 보면 다음과 같습니다.
static Object _workerLocker = new object();
static int _runningWorkers = 0;
int MaxSimultaneousThreads = 5;
foreach(int SomeObject in ListOfObjects)
{
lock (_workerLocker)
{
while (_runningWorkers >= MaxSimultaneousThreads)
{
Monitor.Wait(_workerLocker);
}
}
// check to see if the service has been stopped. If yes, then exit
if (this.IsRunning() == false)
{
break;
}
lock (_workerLocker)
{
_runningWorkers++;
}
ThreadPool.QueueUserWorkItem(SomeMethod, SomeObject);
}
논리는 분명해 보입니다. 스레드 풀에서 공간을 기다렸다가 서비스가 중지되지 않았는지 확인한 다음 스레드 카운터를 늘리고 작업을 대기시킵니다. 를 호출 하는 명령문 내부에서 _runningWorkers
감소 합니다 .SomeMethod()
lock
Monitor.Pulse(_workerLocker)
내 질문은 : 다음lock
과 같이
모든 코드를 단일 안에 그룹화하면 어떤 이점이 있습니까?
static Object _workerLocker = new object();
static int _runningWorkers = 0;
int MaxSimultaneousThreads = 5;
foreach (int SomeObject in ListOfObjects)
{
// Is doing all the work inside a single lock better?
lock (_workerLocker)
{
// wait for room in ThreadPool
while (_runningWorkers >= MaxSimultaneousThreads)
{
Monitor.Wait(_workerLocker);
}
// check to see if the service has been stopped.
if (this.IsRunning())
{
ThreadPool.QueueUserWorkItem(SomeMethod, SomeObject);
_runningWorkers++;
}
else
{
break;
}
}
}
마치 다른 스레드를 조금 더 기다리는 것처럼 보일 수 있지만 단일 논리 블록에서 반복적으로 잠금하는 데 다소 시간이 걸리는 것처럼 보입니다. 그러나 멀티 스레딩을 처음 사용하므로 알지 못하는 다른 문제가 있다고 가정합니다.
_workerLocker
잠긴 다른 장소 는 in을 SomeMethod()
, 감소시키기위한 목적으로 만 _runningWorkers
, 그리고 나서 바깥쪽에 foreach
있는 숫자는 _runningWorkers
0 이되기를 기다렸다가 로깅 및 리턴합니다.
도움을 주셔서 감사합니다.
4/8/15 수정
세마포어 사용을 권장하는 @delnan에게 감사합니다. 코드는 다음과 같습니다.
static int MaxSimultaneousThreads = 5;
static Semaphore WorkerSem = new Semaphore(MaxSimultaneousThreads, MaxSimultaneousThreads);
foreach (int SomeObject in ListOfObjects)
{
// wait for an available thread
WorkerSem.WaitOne();
// check if the service has stopped
if (this.IsRunning())
{
ThreadPool.QueueUserWorkItem(SomeMethod, SomeObject);
}
else
{
break;
}
}
WorkerSem.Release()
내부라고합니다 SomeMethod()
.
SomeMethod
비동기 적으로 호출 합니다. 위의 "잠금"섹션은 새 스레드가 SomeMethod
실행되기 시작하기 직전 또는 그 직후에 남아 있습니다.
Monitor.Wait()
다른 리소스 ( SomeMethod
이 경우)가 잠금을 사용할 수 있도록 잠금을 해제하고 다시 얻는 것이 목적이라는 것을 이해하고 있습니다. 다른 한편으로, SomeMethod
잠금을 획득하고 카운터를 감소시킨 다음 Monitor.Pulse()
해당 메소드에 잠금을 리턴하는 호출을 호출 합니다. 다시, 이것은 내 자신의 이해입니다.
Monitor.Wait
잠금을 해제합니다. 문서를 살펴 보는 것이 좋습니다.