로그인 입점하기
← 가이드 목록
시작하기

Memory Consistency Model이란? 여러 CPU 코어가 메모리 읽기·쓰기를 어떤 순서로 보는지 쉽게 이해하기

Memory Consistency Model은 여러 CPU Core·Thread가 Shared Memory 읽기·쓰기를 어떤 순서로 관찰할 수 있는지 정하는 규칙입니다. Coherence와의 차이·Ordering·Acquire/Release·Happens-Before까지 초보 기준으로 정리합니다.

Memory Consistency Model이란? 여러 CPU 코어가 메모리 읽기·쓰기를 어떤 순서로 보는지 쉽게 이해하기

코드를 `data = 100` 다음 `ready = true`로 쓰면, 다른 Thread가 `ready`를 본 뒤에는 `data`도 100일 것이라고 생각하기 쉽습니다. 그런데 멀티코어 CPU와 Compiler는 성능을 위해 명령·Memory 접근 순서를 바꿀 수 있고, Core마다 Cache·Store Buffer가 있을 수 있습니다. 그래서 한 Thread의 읽기·쓰기가 다른 Thread에게 어떤 순서로 보일 수 있는지를 정하는 규칙이 필요합니다. 이것이 Memory Consistency Model(메모리 일관성 모델)입니다. 서울에서 가격을 바꾼 뒤 「완료」를 올렸는데, 부산에서 완료만 먼저 보고 가격표는 예전 값인 상황과 비슷합니다.

Thread A: data=100 → ready=true
Thread B: if (ready) print(data)
→ 동기화 없이 「ready면 data=100」을 가정하면 위험

Coherence와 다른 점 · 왜 순서가 바뀌나

Cache Coherence는 같은 변수 `x`의 Cache 복사본이 모순되지 않게 맞춥니다. Memory Consistency는 `data`·`ready`처럼 여러 Memory 연산이 다른 Core에서 어떤 순서로 관찰되는가입니다. Out-of-Order Execution으로 독립 명령이 먼저 실행될 수 있고, Compiler도 As-If Rule 안에서 단일 Thread 결과가 같다면 순서를 바꿀 수 있습니다. Write는 Store Buffer에 잠깐 머물 수 있어 다른 Core에게 아직 안 보일 수 있습니다. Visibility는 「변경이 보이는가」, Ordering은 「여러 변경을 어떤 순서로 보는가」입니다.

소스 순서, Store Buffer·재배치, Acquire/Release로 Visibility 보장
소스 순서만으로 다른 Thread의 Visibility·Ordering을 보장하지 않는다. Acquire/Release 같은 동기화가 필요하다

Sequential Consistency · Strong / Weak · Fence

Sequential Consistency는 모든 Memory Operation이 전역 한 줄 순서처럼 보이고, 각 Thread 내부 순서는 유지되는 직관적 모델입니다. 항상 강하게 유지하면 Hardware·Compiler 최적화 여지가 줄어 Strong보다 Weak Memory Model을 쓰는 Architecture도 있습니다. Weak는 「나쁘다」가 아니라 제약이 느슨해 성능 여유가 커질 수 있다는 뜻입니다. x86과 ARM의 Ordering 특성은 다를 수 있어, 저수준 코드가 한 CPU에서만 잘 된다고 다른 CPU를 가정하면 안 됩니다. 일반 개발자는 CPU Fence를 직접 쓰기보다 언어의 Lock·Atomic을 따릅니다. Memory Fence(Barrier)는 특정 경계를 넘어 재배치를 막는 장치이고 공짜가 아닙니다. Fence를 무작정 많이 넣는 것보다 검증된 동기화 API가 보통 더 안전합니다.

Load/Store 조합: LL · LS · SL · SS
Release Store(ready) 앞의 Write가 공개
Acquire Load(ready) 뒤의 Read가 그 Write를 본다

Acquire / Release · Happens-Before · Lock · Atomic

Release는 「여기까지 준비한 Write를 공개」, Acquire는 「신호를 본 뒤부터 그 이전 Write를 제대로 보겠다」는 경계로 이해하면 됩니다. Happens-Before는 시계상 「먼저」가 아니라, Memory Model이 정의하는 「결과가 올바르게 관찰되어야 하는」 관계입니다. `sleep()`은 동기화가 아닙니다. Lock은 Mutual Exclusion뿐 아니라 Visibility·Ordering 보장도 포함되는 경우가 많습니다. Atomic은 Atomicity(한 단위처럼)와 Memory Ordering을 함께 봅니다. Java `volatile`은 Visibility·Ordering에 도움이 되지만 `count++` 같은 복합 연산의 Atomicity까지 주지 않을 수 있습니다. Relaxed Ordering은 Counter처럼 순서 관계가 약할 때만 신중히 씁니다. Lock-Free·CAS는 Contention이 심하면 Retry·Cache Line Ping-Pong으로 느려질 수 있어 무조건 빠르지 않습니다.

Data Race · 언어·웹 · DB Consistency와 구분

Data Race는 같은 Memory에 동기화 없이 동시 접근하고 그중 Write가 있는 경우입니다. Race Condition은 Timing에 따라 결과가 달라지는 더 넓은 말일 수 있습니다. C++ 등에서 Data Race는 Undefined Behavior와 연결될 수 있습니다. 소스 순서 → Compiler 기계어 순서 → CPU 실행 순서를 구분하고, 언어 Memory Model이 이 복잡성을 추상화합니다. 브라우저 일반 JS는 덜 직접적이지만 SharedArrayBuffer·Atomics·Worker에서는 중요합니다. Node Worker Threads·Native Addon, PHP Extension/Shared Memory, Java synchronized·Concurrent Collection도 같은 Shared Memory 문제를 다룹니다. DB Consistency·분산 Strong/Eventual Consistency와는 계층이 다릅니다. SEO 전용 개념은 아니며, 잘못된 동기화로 장애가 나면 서비스 안정성에 간접 영향이 있을 수 있습니다. Immutable·Message Passing·Shared Mutable State 축소는 Ordering 고민을 줄입니다. Debug만 되고 Release만 깨지거나 Heisenbug처럼 재현이 어려운 경우가 많아 Stress Test는 도움이 되지만 「안 터짐 = 증명」은 아닙니다. Correctness 먼저, 측정 후 최적화합니다. Interconnect·NUMA·Contention·Cache Miss와 함께 보면 Shared Memory 비용 그림이 더 잘 맞습니다.

자주 묻는 질문

Memory Consistency Model이란?

여러 CPU Core·Thread가 Shared Memory 읽기·쓰기를 어떤 순서로 관찰할 수 있는지를 정의하는 규칙입니다.

Cache Coherence와 차이는?

Coherence는 같은 위치의 Cache 복사본 일관성, Consistency는 여러 Memory 연산의 관찰 순서입니다.

코드는 위에서 아래로만 실행되나?

단일 Thread 관측 결과는 As-If로 유지되지만, Compiler·CPU는 내부적으로 재배치할 수 있습니다.

sleep으로 해결되나?

아닙니다. 시간 지연은 Memory Synchronization을 보장하지 않습니다.

Lock이면 Visibility도 되나?

언어·Runtime이 제공하는 Lock은 보통 Mutual Exclusion과 함께 Visibility·Ordering 규칙도 제공합니다.

Acquire / Release란?

필요한 Visibility·Ordering 관계를 만드는 Memory Ordering 경계입니다. ready 신호와 data 준비에 자주 짝으로 씁니다.

정리

Memory Consistency Model = 여러 Core·Thread가 Shared Memory 읽기·쓰기를 어떤 순서로 관찰할 수 있는지 정하는 규칙입니다. 소스에서 A 다음 B를 썼다고 동기화 없이 다른 Thread가 반드시 그 순서로 본다고 가정하면 안 됩니다. Compiler·Out-of-Order·Store Buffer·Cache 최적화가 있기 때문입니다. Lock·Atomic·Memory Barrier로 필요한 Visibility와 Ordering(Happens-Before)을 만듭니다. 그런데 순서를 맞춰도 `count = count + 1`처럼 읽기·더하기·쓰기가 여러 단계면, 중간에 다른 Thread가 끼어들어 증가가 사라질 수 있습니다. 이처럼 여러 Thread가 동시에 접근해도 연산이 중간 상태 없이 한 번에 수행된 것처럼 보이게 하는 성질Atomicity(원자성)이라고 합니다.