인프런 커뮤니티 질문&답변
JopQueue관련 질문
작성
·
364
0
void JobQueue::Push(JobRef&& job)
{
const int32 prevCount = _jobCount.fetch_add(1);
_jobs.Push(job); // WRITE_LOCK
// 첫번째 Job을 넣은 쓰레드가 실행까지 담당
if (prevCount == 0)
{
// 이미 실행중인 JobQueue가 없으면 실행
if (LCurrentJobQueue == nullptr)
{
Execute();
}
else
{
// 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다
GGlobalQueue->Push(shared_from_this());
}
}
}
// 일감이 너~무 몰리면?
void JobQueue::Execute()
{
LCurrentJobQueue = this;
while (true)
{
Vector<JobRef> jobs;
_jobs.PopAll(OUT jobs);// Lock걸려있기 때문에 다른 스레드에서 중복되는 일감을 가져갈 수 없다
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) Excute 매서드
if (_jobCount.fetch_sub(jobCount) == jobCount)
_jobCount가 jobCount보다 작아져서 fetch_sub연산 수행 후 언더 플로우가 발생하여 _jobCount가 엄청나게 늘어나는 문제가 발생하지 않는지 궁금합니다.
퀴즈
MMO 서버 환경에서 동시 접속자 증가에 따른 성능 문제를 해결하기 위해 단순 락킹 대신 잡 큐를 사용하는 주된 이유는 무엇일까요?
데이터베이스 접근 속도를 높이기 위해서입니다.
클라이언트와의 통신을 암호화하기 위해서입니다.
여러 스레드가 공유 자원에 효율적으로 접근하고 병목 현상을 줄이기 위해서입니다.
서버 재부팅 없이 업데이트를 적용하기 위해서입니다.
답변 1
0
Rookiss
지식공유자
코드의 흐름상 그런 일은 발생할 수 없습니다.
_jobCount를 조작하는 곳이 Push/Pop 할 때 2 곳이고
그 개수를 _jobs와 맞춰주고 있기 때문입니다.





