스레드 (Thread)
프로그램이 실제로 실행되서 돌아가고 있는 상태를 프로세스라고 한다.
여기서 하나의 프로세스는 최소 한개 이상의 스레드를 가지고 있으며 프로세스 내의 자원을 공유할 수 있다.
이 스레드가 프로그램이 실행되는 기본 단위다.
프로그램은 CPU의 코어에서 실행이 되는데, 코어는 한 번에 한 가지 연산만 할 수 있다.
하지만 컴퓨터가 발전하면서 CPU에 들어있는 코어 수가 늘어났고, 여러 개의 코어를 사용해 동시에 스레드를 실행하고 여러 작업을 병렬적으로 처리할 수 있게 됐다.
이제 C++에서 실제로 스레드를 구현해 사용해 보자
스레드 구현
일단 C++에서 스레드를 사용하기 위해서는 #include <thread>라는 헤더가 필요하다.
#include <iostream>
#include <vector>
#include <chrono>
#include <thread>
#include <memory>
#include <mutex>
using namespace std;
void thFunc1()
{
for (int i=0; i<10; i++)
{
cout << "스레드 1 작동중" << endl;
}
}
void thFunc2()
{
for (int i = 0; i < 10; i++)
{
cout << "스레드 2 작동중" << endl;
}
}
void thFunc3()
{
for (int i = 0; i < 10; i++)
{
cout << "스레드 3 작동중" << endl;
}
}
void main()
{
thread t1(thFunc1);
thread t2(thFunc2);
thread t3(thFunc3);
t1.join();
t2.join();
t3.join();
cout << "함수 종료";
}
그리고 thread를 선언한 다음 thread에서 실행할 함수를 괄호 안에 넣어주면 된다.
thread t1(thFunc1); => t1 스레드에서 thFunc1이라는 함수를 실행하겠다는 뜻!
뒤에 보이는 t1.join()은 t1이라는 스레드의 작업이 종료될 때 까지 기다리겠다는 뜻이다.
실제로 실행한 결과는 아래와 같다.
이번에는 만약 내가 t1스레드와 t2스레드는 병렬적으로 실행하고 싶지만 t3스레드는 t1스레드가 끝나면 실행하고 싶은 경우를 구현해 보자
void main()
{
thread t1(thFunc1);
thread t2(thFunc2);
t1.join();
thread t3(thFunc3);
t2.join();
t3.join();
cout << "함수 종료";
}
join은 스레드의 작업이 종료될 때 까지 기다린다 했으므로, t1.join(); 이후에 스레드를 실행하면 된다.
아래 그림에 보이는 것처럼 스레드 1의 작동이 끝난뒤 실행되는 모습을 볼 수 있다.
+ 여기서 중간 중간 줄이 띄워져 있는 모습을 볼 수 있는데 이는 cout<<에서 endl부분이 나중에 실행되서 겹쳐서 두번나타나 줄이 띄워지게 되는 것이다. 이러한 문제를 해결하려면 printf를 사용하면 된다.
printf는 printf안에 있는 출력이 전부 이루어지는 것을 보장하기 때문이다.
그리고 join() 말고 detach()도 있는데 detach()를 사용할 경우 스레드를 실행 시킨 후 잊어버리는 것이다.
join대신 detach()를 사용할 경우 스레드가 다 실행되기전에 main함수가 종료돼 출력이 덜 될 수 있다.
void main()
{
thread t1(func1);
thread t2(func2);
thread t3(func3);
t1.join();
t2.detach();
t3.detach();
cout << "함수 종료";
}
실제로 join을 사용한 스레드 1은 작업이 보장됐지만, 나머지 2와 3은 detach()를 사용해 main함수가 끝난 뒤 작업이 끝나기전에 종료됐다.
반응형
'C++' 카테고리의 다른 글
[프로그래밍/C++] 헤더파일과 소스파일을 분리하는 이유 (0) | 2024.02.08 |
---|---|
[프로그래밍/C++] 스레드(Thread) 사용하기 (2) (0) | 2024.02.04 |