4. atomic 메모리 순서(memory_order)와 happens-before
난이도 상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C++
// ============================================================================
// [언어 내부동작 문제] C++ - atomic 메모리 순서(memory_order)와 happens-before
// ----------------------------------------------------------------------------
// 주제: std::atomic 의 memory_order(relaxed / acquire / release / seq_cst)가
// 스레드 간 가시성과 재배치에 어떤 의미를 갖는지.
//
// 아래는 한 스레드가 데이터를 준비하고 플래그로 "완료"를 알리면, 다른 스레드가
// 그 플래그를 보고 데이터를 읽는 전형적인 메시지 패싱(message passing) 패턴이다.
// payload 는 일반(비원자) 변수이고, ready 만 atomic 이다.
//
// 과제(코드를 고치는 문제가 아니라, 내부 동작을 예측·설명하는 문제):
// 1) producer/consumer 가 아래처럼 memory_order_relaxed 를 쓸 때, consumer 의 (4)에서
// 항상 42 가 보이는가? payload 접근은 안전한가? 그 이유를 메모리 모델로 설명하라.
// 2) (2)를 release, (3)를 acquire 로 바꾸면 무엇이 "synchronizes-with / happens-before"
// 로 보장되는가? 그때 (4)의 결과와 데이터 경합 여부는?
// 3) memory_order_seq_cst 가 release/acquire 보다 더 보장하는 것은 무엇이며(예: 다중
// 변수 불변식/store-buffering), relaxed 가 정당한 경우(예: 단순 카운터)는 언제인가?
// (먼저 직접 예측을 적은 뒤 answer.md 와 대조할 것)
// ============================================================================
#include <atomic>
#include <thread>
#include <iostream>
std::atomic<bool> ready{false};
int payload = 0; // 일반(비원자) 변수
void producer() {
payload = 42; // (1) 데이터 준비
ready.store(true, std::memory_order_relaxed); // (2) 완료 신호
}
void consumer() {
while (!ready.load(std::memory_order_relaxed)) { // (3) 신호 대기(스핀)
/* busy wait */
}
std::cout << payload << "\n"; // (4) 데이터 읽기
}
int main() {
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
return 0;
} 내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.