1. 스레드(Thread)

프로세스 내에서 실행되는 작은 실행 단위.

프로세스 내에서 생성되며 자원을 스레드 간 공유한다.

(코드, 데이터, 힙 메모리 등을 공유)

 

* 프로세스와 스레드의 차이

- 프로세스는 실행하고 있는 프로그램이다. 다른 프로그램과는 완전히 독립되어 있다.

동시에(병렬적으로) 실행된다.

 

- 스레드는 하나의 프로세스 내에서 생성된다. 스레드 간 메모리에 접근할 수 있다.

병렬적으로 사용하기 위해서는 동기화를 해야 한다.

 

 

2. 멀티 스레드(Multi-Thread)

여러 스레드를 병렬로 사용하여 작업을 수행하는 것.

각 CPU 코어가 각 스레드를 병렬적으로 처리한다.

ex) 쿼드 코어(코어 4개) CPU가 스레드 4개를 1:1 처리

멀티 스레드

각 스레드가 병렬적으로 명령을 처리할 수 있지만, 동일한 힙 메모리 영역을 사용하기 때문에 스레드들이 같은 값을 여러번 고칠 수도 있다.

 

 

3. 스레드 생성

#include <thread>

위의 헤더를 추가하여 스레드를 생성할 수 있다.

void HelloThread()
{
	cout << "Hello Thread" << endl;
}

int main()
{
	std::thread t(HelloThread);

	cout << "Hello Main" << endl;

	while (true)
	{

	}
}

기존의 main 함수를 실행하는 스레드가 있고, 우리가 생성해준 t 스레드(HelloThread 함수를 실행함)가 있다.

main 스레드(부모 스레드)가 종료되었을 때 t 스레드(자식 스레드)가 아직 실행 중이기 때문에 크래시가 발생한다.

따라서 t 스레드를 main 스레드보다 먼저 종료시키거나, main 스레드를 종료시키지 않아야 한다.

(무한 루프를 사용하여 main 스레드를 유지하는 방법을 사용했다)

 

만약 해당 스레드를 종료시키기를 원한다면 join 함수를 사용할 수 있다.

t.join();

 

 

(1) 매개변수 넘기기

void HelloThread(int i) { };

위처럼 t 스레드에서 실행되는 HelloThread 함수가 매개변수를 가질 때 스레드에 해당 매개변수도 같이 넘길 수 있는 문법도 있다.

std::thread t(HelloThread, 100);

 

 

(2) 스레드를 여러 개 만들기

void HelloThread(int i)
{
	while (true)
	{
		cout << "Hello Thread" << i << endl;
	}
}


int main()
{
	vector<thread> threads;

	for (int i = 0; i < 10; i++)
	{
		threads.push_back(thread(HelloThread, i));
	}

	cout << "Hello Main" << endl;

	for (thread& t : threads)
		t.join();
}

vector와 같은 컨테이너를 이용하여 여러 개의 스레드를 만들어 실행할 수 있다.

 

* 컨텍스트 스위칭(Context Switching)

스레드가 무작정 많다고 좋은 것이 아니다. 보통 스레드는 CPU의 코어 개수에 맞춰가는 것이 좋다.

스레드가 코어 개수보다 많아지면 각 코어에서 컨텍스트 스위칭을 통해 한 스레드가 다른 작업으로 스위칭하는 작업이 발생하는데, 이 때 비용이 많이 들게 된다.

 

 

(3) 주의 사항

각 스레드는 각자의 스택 영역을 가진다. 하지만 힙 영역과 데이터 영역을 공유하여 사용하기 때문에 주의하여야 한다.