XV : 쓰레드 풀링
뇌를 자극하는 윈도우즈 시스템 프로그래밍 을 읽고 정리한 문서입니다 ;)
쓰레드 풀에 대한 이해
쓰레드의 생성과 소멸은 시스템에 많은 부담을 준다. 만일 요청받은 작업의 수만큼 쓰레드를 생성하고 처리한 뒤, 쓰레드를 종료시키는 방식이라면 실행 성능은 매우 저하될 것이다.
쓰레드 풀을 유지하는 것은 성능 향상에 도움이 된다. 쓰레드 풀의 기본 원리는 쓰레드의 재활용으로서, 할당된 일을 마친 쓰레드를 소멸시키지 않고 쓰레드 풀에 저장해 뒀다가 필요할 때 다시 쓰는 것이다.
쓰레드 풀은 처리해야 할 일이 등록되기 전에 생성되고, 생성과 동시에 쓰레드들 또한 생성되어 풀에서 대기하게 된다.
지능적인 풀은 처리해야 할 일의 증가 및 감소에 따라서 풀 안의 쓰레드 개수를 늘리기도 하고, 줄이기도 할 것이다.
쓰레드 풀의 구현
쓰레드 풀을 구성하는 데 있어서 정의된 예시 자료형과 함수들은 다음과 같다.
typedef void (*WORK) (void);
typedef struct _WorkerThread {
HANDLE hThread;
DWORD idThread;
HANDLE hEvent;
} WorkerThread;
struct ThreadPool {
DWORD threadCount;
WorkerThread workerThreadList[THREAD_MAX];
CircularQueue<WORK> workList(WORK_MAX);
}
HANDLE hEvent
: 쓰레드에게 일이 부여된다는 것은, 쓰레드가 호출해서 실행할 함수를 지정해 준다는 뜻이다. 만약에 쓰레드에서 할당된 일이 없다면, 쓰레드는WaitFor~
류의 함수 호출을 통해서 Blocked 상태가 되어야 한다. 그리고 새로운 일이 들어왔을 때 잠에서 깨어나 일을 실행해야 한다.typedef void (*WORK) (void)
: 이는 실행될 작업의 단위인, 함수 포인터로서,void function(void);
타입의 함수를 실행하게끔 디자인한 것이다.
위의 간단한 쓰레드 풀을 작동시키는 함수 관계는 다음과 같다.
WORK GetWorkFromPool(void)
: 쓰레드 풀에서 작업할WORK
를 가져올 때 호출하는 함수이다.DWORD AddWorkToPool(WORK work)
: 작업을 새로 쓰레드 풀에 등록할 때 호출하는 함수이다.DWORD MakeThreadToPool(DWORD numOfThread)
: 쓰레드 풀이 생성된 이후에, 풀에 쓰레드를 원하는 개수만큼 생성하는 함수이다.void WorkerThreadFunction(LPVOID pParam)
: 이는 Worker Thread가 실행할 쓰레드의main
함수이다.void WorkerThreadFunction(LPVOID pParam) { WORK workFunction; HANDLE event = myThreadPool.workerThreadList[(DWORD) pParam].hEvent; while(1) { workFunction = GetWorkFromPool(); if (workFunction == NULL) { WaitForSingleObject(event, INFINITE); continue; } workFunction(); } }
쓰레드 풀 작동 메커니즘
- 전역적으로 선언된 쓰레드 풀에
MakeThreadToPool()
함수 호출을 통해 쓰레드를 만들어 등록시킨다. 이렇게 생성된 작업 쓰레드는 이벤트 오브젝트가 Signaled 상태가 되기를 기다리며 Blocked 상태가 된다. AddWorkToPool()
함수 호출을 통해서 Work를 등록한다.- Work가 등록되면, 쓰레드 풀에서 Blocked 상태에 있는 모든 이벤트 오브젝트를 Signaled 상태로 변경한다.
- 모든 이벤트 오브젝트가 Signaled 상태가 되므로, 모든 쓰레드가 Running 상태가 된다. 하지만 Work를 할당받은 하나의 쓰레드를 제외하고 나머지는 다시 Blocked 상태가 되게 한다.
- 작업 쓰레드로 선정된 쓰레드는
GetWorkFromPool()
함수 호출을 통해 받았던 Work를 실행하고, 작업이 끝나면 다시 Blocked 상태로 돌아가게 된다.
이 때, 여러 개의 작업 쓰레드는 물론 메인 쓰레드까지 전역적으로 선언된 쓰레드 풀에 공통으로 접근하기 때문에, 동기화가 필요하다. 뮤텍스를 기반으로 동기화할 수 있을 것이다.
이것만은 알고 갑시다
- 쓰레드 풀링의 이해
- 쓰레드 풀링은 한번 생성한 쓰레드를 재사용해서 시스템의 부담을 덜어주기 위한 기법이다. 이는 쓰레드의 생성과 소멸에 리소스가 상당히 소모되므로 등장한 것이다.
- 여러 개의 작업 쓰레드를 미리 생성하고, 이들은 작업이 등록될 때마다 하나의 쓰레드가 이 작업을 가져가 처리하고, 다음 작업의 할당을 기다리며 Blocked 상태가 된다.
- 쓰레드 풀링의 동작 원리
- 쓰레드 풀링의 동작 원리를 프로그램 코드상에서 공부하는 것은 다양한 의미가 있다.
- 필요한 상황에 최적의 쓰레드 풀을 제공할 수 있고, 풀의 도입여부를 결정하는 데도 도움이 된다.
'공부한 이야기 > 윈도우 OS' 카테고리의 다른 글
XIV : 쓰레드 동기화 기법 II (0) | 2023.04.29 |
---|---|
XIII : 쓰레드 동기화 기법 I (0) | 2023.04.29 |
XII : 쓰레드의 생성과 소멸 (0) | 2023.04.29 |
XI : 쓰레드의 이해 (0) | 2023.04.29 |
X : 컴퓨터 구조에 대한 세 번째 이야기 (0) | 2023.04.29 |