해결된 질문
작성
·
42
·
수정됨
0
해결 ++
아래 질문 내용을 글로벌 큐에서 추가로 처리해 주는 거였습니다.
삭제가 안되서 최상단에 남깁니다.
이것저것 건들면서 연습하다 보니 제 환경에서 글로벌 큐 호출을 안해서 문제였습니다.
안녕하세요?
루키스님 강의를 참고하여 더미 프로젝트 하는 중에 문제가 식별 되어
제가 분석한게 맞다면 강의 코드에 문제가 있어 제보 드려봅니다.
문제라고 생각되는 부분은 JobQueue 클래스인데요,
문제 상황은
부하가 있는 상황에서 '워커스레드를 2개 이상 돌릴 때, Execute()함수가 실행되지 않는'점을 확인하였습니다.
jobCount 관련 변수의 조건이 어디서 안 맞는 것 같아서 생각해보건데,
아래와 같은 경우라고 생각됩니다.
// JobQueue.cpp
void JobQueue::Execute()
{
...
if (_jobCount.fetch_sub(jobCount) == jobCount)
{
// 여기서 다른 워커 스레드의 _jobCount.fetch_add 발생?!
LCurrentJobQueue = nullptr;
return;
}
...
}
}
그렇기 때문의 이후의 잡들이 처리되지 못하고 해당 부분에서 prevCount가 계속 쌓이고 있었습니다.
// JobQueue.cpp
void JobQueue::Push(JobRef job, bool pushOnly)
{
const int32 prevCount = _jobCount.fetch_add(1);
_jobs.Push(job); // WRITE_LOCK
// 여기서 prevCount가 계속 쌓여 0이 아님
if (prevCount == 0)
{
//그러므로 이 부분의 Excute()도 실행되지 않음
...
}
아래는 해당 클래스 cpp 전문입니다.
귀한 시간 내시어 확인해주시면 감사하겠습니다!
#include "pch.h"
#include "JobQueue.h"
#include "GlobalQueue.h"
/*--------------
JobQueue
---------------*/
void JobQueue::Push(JobRef job, bool pushOnly)
{
const int32 prevCount = _jobCount.fetch_add(1);
_jobs.Push(job); // WRITE_LOCK
// 첫번째 Job을 넣은 쓰레드가 실행까지 담당
if (prevCount == 0)
{
// 이미 실행중인 JobQueue가 없으면 실행
if (LCurrentJobQueue == nullptr && pushOnly == false)
{
Execute();
}
else
{
// 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다
GGlobalQueue->Push(shared_from_this());
}
}
}
// 1) 일감이 너~무 몰리면?
void JobQueue::Execute()
{
LCurrentJobQueue = this;
while (true)
{
vector<JobRef> jobs;
_jobs.PopAll(OUT jobs);
const int32 jobCount = static_cast<int32>(jobs.size());
for (int32 i = 0; i < jobCount; i++)
jobs[i]->Execute();
// 남은 일감이 0개라면 종료
if (_jobCount.fetch_sub(jobCount) == jobCount)
{
LCurrentJobQueue = nullptr;
return;
}
const uint64 now = ::GetTickCount64();
if (now >= LEndTickCount)
{
LCurrentJobQueue = nullptr;
// 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다
GGlobalQueue->Push(shared_from_this());
break;
}
}
}
답변 1
0
안녕하세요, 인프런 AI 인턴입니다. mhyim님.
현재 질문하신 부분은 JobQueue의 다중 스레딩에서 발생할 수 있는 잠재적인 경쟁 상태 문제가 있는 것으로 보입니다. 주로 _jobCount
값의 증감과 관련된 부분에서 여러 스레드가 동시에 접근하면서 예상치 않은 결과가 발생할 수 있습니다. 이 경우, fetch_add
및 fetch_sub
연산이 비원자적으로 작동하거나 동시성 문제로 인해 _jobCount
가 제대로 관리되지 않을 수 있습니다.
비슷한 문제를 언급한 강의 질문이 있어 참고하시면 좋을 것 같습니다.
이 문제를 해결하기 위해 다음과 같은 방법들을 고려해볼 수 있습니다:
Push
와 Execute
함수의 fetch_add
및 fetch_sub
연산 사이에 추가적인 동기화 메커니즘을 통해 동시 실행 시 문제를 방지해야 합니다._jobCount
의 사용을 보다 신중히 확인하여 여러 스레드 환경에서 일관성을 유지할 수 있도록 해야 합니다.또한, 데이터의 안전한 처리를 위해 _jobs.Push(job)
와 같은 큐 조작 부분에도 추가적인 락 메커니즘이 필요할 수 있습니다.
추가적인 코드 문제와 스레드 관리에 대한 더 깊은 논의는 강의 제공자와의 상의를 통해 해결해야 할 수도 있습니다. 질문을 통해 상황을 자세히 설명해 주신 만큼 같은 문제를 겪고 있는 다른 수강생들에게도 큰 도움이 될 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.