• 카테고리

    질문 & 답변
  • 세부 분야

    시스템

  • 해결 여부

    해결됨

0강 Win32 작업자 스레드 동기화 9:33~

23.12.01 13:12 작성 23.12.01 14:55 수정 조회수 189

0

DWORD WINAPI ThreadFunction(LPVOID pParam)
{
	puts("*** Begin Thread ****");
	for (int i = 0; i < 5; ++i)
	{
		printf("[Worker thread] %d\n", i);
		::Sleep(1);
	}

	//스레드가 끝나기 전에 이벤트를 세트한다.
	puts("종료 이벤트 세트 전");
	//이 함수를 호출하면 _tmain() 함수의
	//WaitForSingleObject() 함수가 반환한다!
	::SetEvent((HANDLE)pParam);
	puts("종료 이벤트 세트 후");
	puts("**** End Thread ****");
	return 0;
}
for (int i = 0; i < 5; i++)
	{
		printf("[Main thread] %d\n", i);
		//i값이 3이면 이벤트가 세트되기를 무한정 기다린다!
		if (i == 3 &&
			::WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0)
		{
			puts("종료 이벤트를 감지했습니다!");
			::CloseHandle(hEvent);
			hEvent = NULL;
		}
	}

3일 때 worker 스레드가 실행되는 조건문 하에서

Main함수가 2일 때도 반환되고 0일 때도 반환됩니다.

말씀해주신대로 3일 때 반환되는 경우도 있지만 보장되지 않고 빈번하게 아래 케이스처럼 반환되는 경우가 있습니다.(디버그 모드, 릴리즈 모드 모두에서)

이는 무슨 이유 때문인지 궁금합니다.

 

case1

[Main thread] 0

[Main thread] 1

[Main thread] 2

*** Begin Thread ****

[Worker thread] 0

[Main thread] 3

[Worker thread] 1

[Worker thread] 2

[Worker thread] 3

[Worker thread] 4

종료 이벤트 세트 전

종료 이벤트 세트 후

**** End Thread ****

종료 이벤트를 감지했습니다!

[Main thread] 4

 

case2

[Main thread] 0

*** Begin Thread ****

[Main thread] 1

[Main thread] 2

[Worker thread] 0

[Main thread] 3

[Worker thread] 1

[Worker thread] 2

[Worker thread] 3

[Worker thread] 4

종료 이벤트 세트 전

종료 이벤트 세트 후

**** End Thread ****

종료 이벤트를 감지했습니다!

[Main thread] 4

답변 2

·

답변을 작성해보세요.

0

기존 예제에서 코드를 변경하지 않은 것이라면 다음과 같은 생각을 할 수 있습니다.

  1. 메인 스레드에서 i값이 3이 되고 WaitForSingleObject() 함수가 호출되는 순간은 앞서 작업자 스레드를 생성하고 실행하는 반복문 이후 입니다. 그러나 스케줄링 문제로 생성한 작업자 스레드부가 실행되기 전에 메인 스레드에서 i값이 3이 될 수 있습니다.

  2. 스레드를 생성하고 실행시켰다 해서 즉시 실행으로 이어지지는 않습니다. 생성된 작업자 스레드가 스케줄러에 의해 선택되고 CPU자원을 할당 받아야 실제로 연산이 시작 됩니다. 작업자 스레드 생성 및 요청 코드가 실행되는 메인 스레드는 작업자 스레드 코드가 실행되기 전에 i 값이 3이 될 수 있습니다.

  3. 메인 스레드에서 i값이 3이 되기 전에 작업자 스레드 중 일부가 실행 상태에 진입하고 심지어 메인 스레드가 WaitForSingleObject() 함수를 호출하기도 전에 이벤트를 세트하고 종료 될 수 있습니다. 물론 이를 방지하기 위해 Sleep() 함수를 호출해 대략 5ms 이상 지연이 발생하도록 유도 했지만 CPU가 어떤 순서로 스레드를 스캐줄링 할지는 알 수 없습니다. 이 지점부터 '우연'이라는 개념이 생겨납니다.

  4. 지금까지 설명한 것들과 별개로 어떤 경우라 하더라도 메인 스레드에서 i값이 4가 되는 경우는 작업자 스레드가 이벤트를 세트한 이후가 될 수 밖에 없습니다.

참고하시기 바랍니다. :)

0

작성한 전체 예제를 올려주셔야 정확한 답변이 가능합니다. 다만 부분적인 코드로 추측해 답변을 드리자면...

메인 스레드에서 WaitForSingleObject() 함수가 대기하기 전에 이미 작업자 스레드의 이벤트가 셋트된 것은 아닌지 생각 해볼 필요는 있겠습니다. 참고하시기 바랍니다. :)

GOLD D님의 프로필

GOLD D

질문자

2023.12.02

답변 감사합니다, 강의에 나온 스레드 동기화 예제 파일 코드 그대로라서 전체 코드를 올리지 않았습니다. 강사님과 동일 코드인데 결과물이 다른 경우들이 발생하여 질문드렸습니다.