• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

JobTimer 강의 관련 질문을 드립니다.

23.04.09 01:08 작성 23.04.09 01:09 수정 조회수 573

0

안녕하세요. 선생님.
항상 좋은 강의를 위해 고생많으십니다.

다름이 아니라 JobTimer강의를 보던 도중 Atomic과 lock을 함께 사용하여서 TimerItem을 꺼내는 코드를 작성해주셨는데요.
아래와 같이 2가지 사항이 궁금합니다.

1. lock과 Atomic을 함께 쓰시는 경우는 특정 컨테이너에서 작업을 다 꺼내고 추가적인 작업을 할 경우, lock 점유 시간을 줄이고 싶으실 때에 Atomic을 함께 사용하시는 것이라 보면 될까요?

2. 이것이 맞다면, 보통 Atomic을 함께 써야하는 'lock 점유 시간이 긴' 작업은 어떤 기준으로 판단하시는 지가 궁금합니다.

시간내주시고 확인해주셔서 감사합니다.

답변 1

답변을 작성해보세요.

0

네 맞습니다.
기본적으로 Atomic이 더 가벼운 상황에서 사용할 수 있는데요.
(int UserCount관리라거나, bool Disconnected 등)

그러나 코드를 만들다 보면, 변수 1개를 대상으로 작업하는게 아니라
더 큰 범위에 대한 코드 동기화가 필요할 수도 있습니다.
아무리 atomic 변수라 해도 따로 따로 처리하면 안 되고
묶어서 한 방에 수정해야 하는 경우가 생길 수도 있는데
그런 경우는 Lock을 잡아야겠죠.

사실 기본적으로 atomic으로만 처리할 수 있으면 더 좋지만,
코드가 딱 한줄 (데이터 한개)만 동기화가 필요한 경우는 많이 없어
Lock까지 가야하는 상황이 거의 빈번합니다.

머어니님의 프로필

머어니

질문자

2023.04.09

주말이신데 답변 달아주셔서 정말 감사합니다.

2번에서 질문드렸던, Atomic과 lock을 함께 써서 lock을 적게 잡아야할 정도로 민감한 작업에 대한 판단 기준도 여쭤볼 수 있을까요?

개략적으로 제가 생각하기로는 특정 컨테이너에 있는 작업을 다 꺼내서 for문을 돌아야 하는 작업이 있다면, 저런 식으로 lock을 최소화할 수 있다고 생각이 드는데, 선생님께서 이런 경우와 관련된 판단 기준이 있으시다면 듣고자 하여 여쭤봅니다.

아래는 선생님께서 작성해주신 코드입니다.

void JobTimer::Distribute(uint64 now)
{

	// 한 번에 1 쓰레드만 통과

	if (_distributing.exchange(true) == true)

		return;

	Vector<TimerItem> items;

	{

		WRITE_LOCK;

		while (_items.empty() == false)

		{

			const TimerItem& timerItem = _items.top();

			if (now < timerItem.executeTick)

				break;

			items.push_back(timerItem);

			_items.pop();

		}

	}

	for (TimerItem& item : items)

	{

		if (JobQueueRef owner = item.jobData->owner.lock())

			owner->Push(item.jobData->job);

		ObjectPool<JobData>::Push(item.jobData);

	}

	// 끝났으면 풀어준다

	_distributing.store(false);

}