스레드와 동기화
1. std::thread, std::mutex, std::lock_guard
C++11에서 도입된 std::thread는 멀티스레드를 사용하여 병렬로 작업을 처리할 수 있도록 도와주는 라이브러리입니다. 스레드 간의 자원 경쟁을 방지하려면 std::mutex와 std::lock_guard를 사용하여 동기화할 수 있습니다.
1.1. std::thread
std::thread는 새로운 스레드를 생성하고, 해당 스레드에서 실행할 함수를 지정하는 데 사용됩니다.
#include <iostream>
#include <thread>
void printMessage() {
std::cout << "Hello from thread!" << std::endl;
}
int main() {
std::thread t(printMessage); // 스레드 생성
t.join(); // 스레드가 종료될 때까지 기다림
return 0;
}
1.2. std::mutex와 std::lock_guard
std::mutex는 스레드 간에 공유 자원에 대한 동시 접근을 방지하는데 사용됩니다. std::lock_guard는 mutex를 자동으로 잠그고 해제하는 RAII(자원 관리 기법) 클래스로, 예외 발생 시에도 자동으로 해제됩니다.
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void printMessage(int id) {
std::lock_guard<std::mutex> guard(mtx); // mutex 잠금
std::cout << "Thread " << id << " is printing." << std::endl;
}
int main() {
std::thread t1(printMessage, 1);
std::thread t2(printMessage, 2);
t1.join();
t2.join();
return 0;
}
2. 병렬 알고리즘 ()
C++17부터는 헤더를 사용하여 병렬 알고리즘을 쉽게 구현할 수 있습니다. 이를 통해 반복문이나 알고리즘을 병렬로 실행할 수 있습니다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <execution>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 병렬 알고리즘으로 벡터의 값 두 배로 만들기
std::for_each(std::execution::par, vec.begin(), vec.end(), [](int& n) {
n *= 2;
});
for (int n : vec) {
std::cout << n << " "; // 출력: 2 4 6 8 10
}
return 0;
}
3. 원자 연산 (std::atomic)
std::atomic은 스레드 간의 안전한 데이터 공유를 위해 제공되는 클래스입니다. 이를 사용하면 원자적으로 데이터를 읽고 쓸 수 있어 동기화 없이 멀티스레딩 환경에서 안전하게 작업을 처리할 수 있습니다.
#include <iostream>
#include <thread>
#include <atomic>
std::atomic<int> counter(0);
void incrementCounter() {
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1, std::memory_order_relaxed);
}
}
int main() {
std::thread t1(incrementCounter);
std::thread t2(incrementCounter);
t1.join();
t2.join();
std::cout << "Final counter value: " << counter.load() << std::endl; // 출력: 2000
return 0;
}