#include <iostream>
#include <algorithm>
#include <vector>
#include <thread>
#include <execution>
void foo(int n)
{
std::cout << n << " : " << std::this_thread::get_id() << std::endl;
}
int main()
{
std::vector<int> v{1,2,3,4,5,6,7,8,9,10};
//std::for_each(v.begin(), v.end(), foo);
std::for_each(std::execution::par, v.begin(), v.end(), foo);
// std::execution::par(C++17~) : 병렬로 실행해 주세요
// 모두 다른 thread로 실행이 된다.
}
주의사항
#include <iostream>
#include <algorithm>
#include <vector>
#include <thread>
#include <execution>
#include <mutex>
#include <chrono>
using namespace std::literals;
int main()
{
std::vector<int> v(100, 0);
for(int i = 1; i < 100; i++)
v.push_back(i);
int sum = 0;
std::for_each(std::execution::par, v.begin(), v.end(), [&](int n) {
sum += n;
std::this_thread::sleep_for(1ms);
});
// 스레드 세이프하지않기에 5050이 나오지 않게된다.
std::cout << sum << '\n';
}
해결해보자
int main()
{
std::vector<int> v(100, 0);
for(int i = 1; i < 100; i++)
v.push_back(i);
std::mutex m;
int sum = 0;
std::for_each(std::execution::par, v.begin(), v.end(), [&](int n) {
std::lock_guard<std::mutex> lg(m);
// mutex는 성능저하가 있다
sum += n;
std::this_thread::sleep_for(1ms);
});
std::cout << sum << '\n';
}
int main()
{
std::vector<int> v(100, 0);
for(int i = 1; i < 100; i++)
v.push_back(i);
std::atomic<int> sum = 0;
std::for_each(std::execution::par, v.begin(), v.end(), [&](int n) {
//sum += n;
sum.fetch_add(n, std::memory_order_relaxed);
std::this_thread::sleep_for(1ms);
});
std::cout << sum << '\n';
}
atomic smart pointer(C++20)
#include <iostream>
#include <thread>
#include <atomic>
#include <memory>
void foo()
{
std::shared_ptr<int> ptr = std::make_shared<int>(5);
// 값에 의한 참조로 ptr이 복사되며 또 만들어 질 것이다.
std::thread t1([ptr]() mutable
{
// ptr이 새로 만들어지며 기존의 ref를 하나 줄일것인데
// 그 ref가 동기화 될것인가??
// 일단 스레드 세이프하다.
ptr = std::make_shared<int>(1);
});
std::thread t2([ptr]() mutable
{
ptr = std::make_shared<int>(2);
});
t1.join();
t2.join();
}
만약 참조에 의한 캡쳐라면?
#include <iostream>
#include <thread>
#include <atomic>
#include <memory>
void foo()
{
std::shared_ptr<int> ptr = std::make_shared<int>(5);
std::thread t1([&ptr]() mutable
{
ptr = std::make_shared<int>(1);
});
std::thread t2([&ptr]() mutable
{
ptr = std::make_shared<int>(2);
});
// ptr이 참조값이고 두 개의 스레드가 동시에 ptr를 변경하려한다.
// 스레드 세이프하지 못한 코드이다.
t1.join();
t2.join();
}
해결해보자
void foo()
{
// atomic의 smart pointer 특수화 버전, 단, C++20부터 지원됨
std::atomic<std::shared_ptr<int>> ptr = std::make_shared<int>(5);
std::thread t1([&ptr]() mutable
{
ptr = std::make_shared<int>(1);
});
std::thread t2([&ptr]() mutable
{
ptr = std::make_shared<int>(2);
});
t1.join();
t2.join();
}