본문 바로가기

개인 공부/네트워크

네트워크P-010(스레드 기다리기 & 재실행)

스레드 제어

  • 스레드는 윈도우 운영체제의 실행 단위므로, 우선 순위를 변경하거나 실행을 중지하고 재시작하는 등의 제어기능을 윈도우 API에서 지원해준다
  • 스레드 우선 순위 변경
    • 각 스레드에 CPU 시간을 적절히 분배하기 위한 정책!!
    • 스레드 스케줄링 OR CPU스케줄링 --> 우선 순위가 높은 것을 우선적으로 할당한다!
  • 스레드 우선 순위를 결정하는 요소
    • 프로세스 우선 순위 (우선 순위 클래스) : 프로세스 속성으로, 같은 프로세스가 생성한 스레드는 우선순위 클래스가 모두 같다!!!
    • 스레드 우선 순위 (우선 순위 레벨) : 스레드 속성으로, 같은 프로세스에 속한 스레드 간 상대적인 우선 순위를 결정할 때 사용한다

 

  • 우선 순위 클래스
REALTIME_PRIORITY_CLASS(실시간)
HIGH_PRIORITY_CLASS(높음)
ABOVE_NORMAL_PRIORITY_CLASS(높은 우선순위)
NORMAL_PRIORITY_CLASS(보통)
BELOW_NORMAL_PRIORITY_CLASS(낮은 우선순위)
IDLE_PRIORITY_CLASS(낮음)
  • 우선 순위 레벨
THREAD_PRIORITY_TIME_CRITICAL
THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_ABOVE_NOLMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_IDLE

 


스레드 스케줄링 방식

  • 우선 순위가 가장 높은 스레드에 CPU시간을 할당한다
  • 우선 순위가 같은 스레드가 여러개 있을 때는 CPU시간을 번갈아 가며 할당한다

 

  • 우선순위가 높은 스레드가 계속 CPU시간을 요구하면 우선순위가 낮은 스레드는 CPU시간을 전혀 할당 받지 못하는 기아 문제가 생긴다
  • 기아 문제 해결
    • OS는 기아 문제가온 스레드의 우선순위를 단계적으로 끌어 올려 우선순위가 낮은 CPU도 사용할 수 있게한다

우선순위 레벨 조작 함수

  • 응용프로그램이 직접 우선 순위를 변경하기도 한다

SetThreadPrioity : 우선 순위 변경 함수

#include <windows.h>
BOOL SetThreadPriority(
	HANDLE hThread,	// 스레드 핸들
	int nPrioriy	// 우선 순위 레벨
);

// 성공 : 0이 아닌 값들
// 실패 : 0

GetThreadPriority : 우선 순위를 알고 싶을 때 사용하는 함수

#include <windows.h>
int GetThreadPriority(
	HANDLE hThread	// 스레드 핸들
);

// 성공 : 우선순위 레벨
// 실패 : THREAD_PRIORITY_ERROR_RETURN

 

 


스레드 종료 기다리기

  • 스레드는 일단 생성되면 CPU 시간을 사용하려고 다른 스레드와 경쟁하면서 독립적으로 실행한다

WaitForSingleObject( ) 함수

  • 특정 스레드가 종료될 때까지 기다린다 -> 1개의 스레드를 생성
#include<windows.h>
DWORD WaitForSIngleObject(
	HANDLE hHandle,	// 상대 스레드
	DWORD dmMilliseconds	// 대기 시간 밀리초
);
// 성공 : WAIT_OBJECT_0 또는 WAIT_TIMEOUT
// 실패 : WAIT_FAILED
  • hHandle : 종료를 기다릴 대상 스레드
  • dwMilliseconds : 대기 시간(밀리초) -> 대기 시간이 지나도 종료되지 않으면 WAIT_FAILED리턴이된다
  • 대기시간으로 INFINITE값을 사용하면 스레드가 종료할때까지 기다린다

WaitForMultipleObject() 함수

  • 둘 이상의 스레드가 종료될 때까지 기다린다 
#include<windows.h>
DWORD WaitForMulitpleObjects(
	DWORD nCount, const HANDLE *lpHandles,	// 모든 스레드 핸들
	BOOL bWaitAll,	// 스레드들이 종료되었는지 확인
	DWORD dmMilliseconds	// 대기 시간 밀리초
);
// 성공 : WAIT_OBJECT_0 또는 WAIT_TIMEOUT
// 실패 : WAIT_FAILED
  • nCount, lpHandles : 스레드 핸들을 배열에 넣어서 전달한다
    • nCount : 배열 크기
    • lpHandles : 배열의 시작 주소
  • bWaitAll : 모든 스레드가 종료됐는지 체크 (TRUE : 모든 스레드 종료 / FALSE : 한스레드 종료하는 즉시 리턴)

스레드 실행 중지와 재실행

  • 실행 중지 함수 : 스레드 핸들을 보유하고 있으면 해당 스레드 실행을 일시 정지
#include<windows.h>
DWORD SuspendThread(
	HANDLE hThread	// 스레드 핸들
);

// 성공 : 중지 횟수
// 실패 : -1
  • 재실행 함수
#incldue <windows.h>
DWORD ResumeThread(
	HANDLE hThread	// 스레드 핸들
);

// 성공 : 중지 횟수
// 실패 : -1
  • OS에서 스레드 중지 횟수를 관리한다
    • SuspendThread()함수를 호출할 때마다 1씩 증가
    • ResmeThread()함수를 호출할 때마다 1씩 감소
  • 중지 횟수가 0보다 크면 스레드는 실행중지 상태이다

 

실행 중지 함수 Sleep()

void Sleep(
	DOWRD dwMilliseconds	// 밀리초
);
  • Sleep()함수를 호출하면 밀리초로 지정한 시간이 지나면 자동으로 재시작한다

스레드 기다리기 재실행 실습

#include "Common.h"

int sum = 0;
DWORD WINAPI MyThread(LPVOID arg){
	int num = (int)arg;
	for (int i = 1; i <= num; i++)
		sum += i;
	return 0;
}

int main() {
	int num = 100;
	HANDLE hThread = CreateThread(NULL, 0, MyThread, (LPVOID)num, CREATE_SUSPENDED, NULL);	// 스레드 생성 
	if (hThread == NULL)	return 1;

	printf("스레드 실행 전!\n계산 결과 = %d\n", sum);
	ResumeThread(hThread);	// 스레드 재실행!
	WaitForSingleObject(hThread, INFINITE);		// 스레드 종료 기다리기
	printf("스레드 실행 후!\n계산 결과 = %d\n", sum);
	CloseHandle(hThread);
	return 0;
}