[Server Programming/cpp] 멀티스레드 예제 - 소수 찾기
전체 코드
#include <iostream>
#include <vector>
#include <chrono>
#include <thread>
#include <memory>
#include <mutex>
using namespace std;
const int MaxCount = 150000;
const int ThreadCount = 4;
//소수인지 판단
bool IsPrimeNumber(int number){
if (number == 1) return false;
if (number == 2 || number == 3) return true;
for (int i = 2; i < number - 1; i++) {
if ((number % i) == 0) {
return false;
}
}
return true;
}
//출력
void PrintNumbers(const vector<int>& primes) {
for (int v : primes) {
cout << v << endl;
}
}
int main() {
//변수 정의
int num = 1;
vector<int> primes;
recursive_mutex num_mutex; //num 변수를 락할때 필요한 mutex 변수 선언
recursive_mutex primes_mutex; // ""
auto t0 = chrono::system_clock::now();
//작동할 워커 스레드
vector<shared_ptr<thread>> threads;
for (int i = 0; i < ThreadCount; i++)
{
//외부 변수를 참조 캡쳐하여 쓰레드를 생성 * [&] 참조 캡처 : 람다 함수 내부에서 외부 변수 자체, 실제 값을 변경할 수 있다.
//공유 변수를 사용하는 경우, 특히 동기화일때 참조 캡처를 사용해야 동기화를 이룰 수 있다.
shared_ptr<thread> thread(make_shared<thread>([&]() {
//각 스레드의 메인 함수
//값을 가져올 수 있으면 루프를 돈다.
while (true)
{
int n;
{
//num을 락시킨다.
lock_guard<recursive_mutex> num_lock(num_mutex);
n = num;
num++;
} // 스코프를 벗어나면서 num_lock 지역 변수가 삭제되며, unlock이 자동적으로 실행된다.
if (n >= MaxCount) break;
//소수인 경우
if (IsPrimeNumber(n)) {
//접근할 primes에 락을 건 후 소수를 리스트에 넣어준다.
lock_guard<recursive_mutex> primes_lock(primes_mutex);
primes.push_back(n);
} // 여기도 마찬가지로 스코프를 벗어나며 unlock실행
}
}));
//쓰레드 객체를 쓰레드 벡터에 가지고 있는다.
threads.push_back(thread);
}
//모든 스레드가 일을 마칠때까지 대기한다.
for (auto thread : threads) {
thread->join();
}
auto t1 = chrono::system_clock::now();
auto duration = chrono::duration_cast<chrono::milliseconds>(t1 - t0).count();
cout << "Took " << duration << "milliseconds." << endl;
return 0;
}
스마트 포인터와 뮤텍스 클래스를 사용해 코드의 안정성을 높였다.
lock_guard의 역할
이 클래스는 스코프가 종료될 때 자동으로 뮤텍스를 해제한다.
recursive_mutex는 뮤텍스를 재귀적으로 잠글 수 있게 해주는 뮤텍스 타입.
lock_guard 객체가 생성되면서 뮤텍스를 잠근다.
lock_guard 객체가 소멸되면, 해당 뮤텍스를 자동으로 해제한다.
예외가 발생하더라도 뮤텍스가 해제되므로, 코드의 안정성을 높여준다.
본 코드에서는 lock_guard<recursive_mutex> num_lock(num_mutex); 와 같이 num_mutex를 잠그고 num 변수에 접근하였다.
결론
thread 클래스를 사용해서 멀티 스레드 프로그램을 작성해보았다. 뮤텍스 기법을 사용해 자원을 동기화하여 문제없이 cpu의 다중 스레드를 효율적으로 사용해 프로그램의 속도를 높이는 것이 가능했다.