프로그래밍 언어/Effective Modern C++

[Effective Modern C++] 항목 35 ~ 40 : 동시성 API

우향우@ 2024. 12. 15. 18:35

항목 36 : std::thread, std::async

std::thread t(doAsyncFunctionPointer)는 실제 시스템 스레드를 생성하여 넘겨준 함수 포인터를 실행시킨다. 이러한 std::thead를 활용하는 것을 스레드 기반 프로그래밍이라고 한다. 이때 무조건 시스템 스레드를 생성하기에 스레드 고갈, 과다 구독, 부하 균형화 등의 스레드 관리를 수동으로 모두 해야한다.

auto f = std::async( doAsyncFunctionPointer)는 넘겨준 함수 포인터를 사용자 관점에 비동기 동시적으로 테스크라는 단위로써 수행해주는데 무조건 시스템 스레드를 생성하지는 않는다. 대신 내부적으로 알아서 적절하게 시스템 스레드를 할당하고 적절하게 분배하여 수행한다. 따라서 위에서 언급한 스레드 관리를 자동으로 해준다.

보통 환경 및 다른 프로세스의 상태에 따라 스레드 관리가 달라지기에 프로그래머 스스로 관리하기 보단 async에 맡기는게 좋다. 또한 async는 리턴되는 future 객체를 통해 함수 리턴값 및 예외도 받을 수 있기에 유용하다. 따라서 특수 목적이 있는게 아니라면 async를 쓰자. 

 

항목 40 : std::atomic, volatile 차이

std::atomic과 volatile은 각각 보장해주는 것이 다르다.

 

std::atomic

1. 읽기, 쓰기, 증가등의 연산에 대해 스레드 간 원자성 보장

2. 코드 순서 바꾸는 최적화  방지

-> 멀티 스레드 용에 적합

 

volatile

1. redundant loads, dead stores 최적화 방지

int x;
x = 10; //최적화로 없어질 수 있음
x = 20;
auto y = x; 
y = x; // 최적화로 없어질 수 있음.

//x가 volatile int면 최적화 안함.

-> 메모리 대응 입출력(외부 IO에서 특정 메모리를 읽고 쓰는 경우)에 적합

 

 

+ 개인 의문점) 멀티 스레드에서도 volatile이 필요하지 않나?