Quick Reference
atomic counter increment -> one indivisible read-modify-write
atomic flag publish -> value + ordering contract required
multi-field invariant -> atomic one field alone is usually insufficientAtomic은 특정 연산이 다른 thread에 중간 단계로 관찰되지 않게 합니다. 프로그램 전체의 여러 값과 순서를 자동으로 안전하게 만드는 키워드는 아닙니다.
원자성과 순서
Counter 증가처럼 독립된 한 값의 read-modify-write는 atomic 연산과 잘 맞습니다. 하지만 balance와 transactionCount를 함께 갱신해야 하는 불변식은 각각을 atomic으로 만들기만 해서는 두 값의 일관된 snapshot을 보장하지 못할 수 있습니다.
Compiler와 CPU는 허용된 범위에서 memory operation을 재배치할 수 있습니다. Atomic API의 memory order는 값 자체의 원자성뿐 아니라 앞뒤 operation이 다른 thread에 보이는 순서를 정의합니다.
relaxed -> 해당 atomic 값의 원자성만 요구, 다른 memory의 publish 순서 없음
release store -> 앞선 write를 publish
acquire load -> 대응하는 release가 publish한 write를 관찰
acq_rel -> read-modify-write에서 acquire와 release를 함께 적용
seq_cst -> acquire/release에 더해 단일 전역 순서 제약 제공Release를 관찰한 acquire 사이에는 happens-before 관계가 만들어질 수 있습니다. 이 계약을 증명하기 어렵다면 언어 기본 순서나 mutex를 사용하고, 측정 없이 relaxed부터 선택하지 않습니다.
Lock-free 판단
Lock-free는 항상 wait-free이거나 항상 빠르다는 뜻이 아닙니다. Contention이 높으면 compare-exchange 재시도가 반복될 수 있고, ABA와 memory reclamation 같은 어려운 문제가 생깁니다.
단순 lock으로 요구사항과 성능을 만족하면 그것이 더 안전한 기본값입니다. Atomic 구조는 benchmark와 명확한 ownership 규칙이 있을 때 선택합니다.
자주 틀리는 점
volatile을 thread synchronization 도구로 사용하지 않습니다.- 여러 atomic load 사이에 일관된 전체 snapshot이 자동으로 생기지 않습니다.
- lock-free 여부는 type과 platform 구현에 따라 달라질 수 있습니다.
- compare-exchange 실패 시 갱신되는 expected 값과 재시도 loop를 API 계약대로 처리합니다.
참고 링크
2 sources