atomic 을 사용한다고 가시성이 해결 되지 않고 단지
동일한 객체에 대해서 동일한 수정순서를 관찰 할 수가 있다
수정 순서란 : 이전에 B 값에서 C 값으로 바뀐 순서를 말하며 B 로 수정순서가 완료됐었을때는 B 이전의 상태인 A 로 되돌아가지 못한다 ( A 가 과거의 값이였다는 가정하에)
그래서 atomic 을 사용한다고 해서 가시성과 코드 재배치의 문제가 해결 되지 않는다
하지만...
B 에서 C로 아직 바뀌지 않은 상태는 현재 cpu 에서 캐쉬쪽은 최신 값일순 있어도 아직 메모리에는 이전 값이 있게 되는 현상을 말한다
즉 atomic 을 사용했어도 이 현상이 있기 때문에
가시성, 코드 재배치 문제의 해결이 되지 않음 단지 동일한 객체에 대해서 다른스레드 들에서 동일한 수정순서는 관찰 할수 있다
그런데 atomic 을 사용할대 뒤의 인자 memory_order:.... 를 어떤걸 쓰느냐에 따라
가시성과 코드 재배치의 문제가 해결이 되느냐 안되느냐가 결정이 된다
ex : memory_order::memory_order_seq_cst
1. Sequentially consistent (가장 엄격, 최적화 여지 적음) seq_cst , default 버전
가시성, 코드 재배치 문제가 해결된다 , 그냥 atomic 을 쓰면 default 인자로 memory_order::memory_order_seq_cst 이 들어가기 때문에 가시성과 코드 재배치 문제가 해결된다
2. Acquire-Release ( acquire , release) : 두개를 써주는데 이 경우에는
memory_order::memory_order_release :
release명령 이전 메모리 명령들이, 해당 명령 이후로 재배치 되어 들어가는것을 막아준다
즉 release 위에 있는 것들음 메모리 명령 재배치가 일어날 수는 있다는 것
그리고 acquire 로 같은 변수를 읽는 스레드가 있다면
memory_order::memory_order_acquire
release 이전의 명령들이 acquire 하는 순간에 관찰 가능 해진다 (즉 가시성이 보장이 된다는 것)
즉 acquire 아래 있는 명령들이 acqurie 위로 올라가는 재배치를 막아 준다는 것이면서
release 이전의 내용들이 acquire 이후에는 모두다 메모리에서 제대로 보여지는 상태가 보장이 되어
가시성이 보장이 된다는 것이다
release 이전의 value = 10 이 acqure 이후에는 value 에서는 가시성이 보장이 acquire 로 되었음으로
acquire 이후로 정확하게 가시성을 보장받아 value== 10 이 된다
그래서 1,3 주간 단계라 할 수 있다
3) Released (relaxed) : memory_order::memory_order_relaxed
최적화 여지가 많음
코드 재배치와 가시성이 해결되지 못하고,
단지 동일객체에 대한 동일 수정순서만 보증해준다 (즉 현재 값 B 과 변경 예상인 값C 들 보다 더 과거 값이(A) 되진 않는다는 것 )
정리하자면 1,2 번을 쓰고 왠만하면 seq_cst 를 쓰자
그런데 Intel, AMD 에서는 seq_cst 를 자체적으로 보장해줘서 seq_cst 를 기본으로 써도 성능차이는 거의 나지 않는다 하지만 ARM 에서는 차이가 발생한다
자바에선 volatile키워드로 가시성 문제를 해결하는데 c++ 은 단지 코드 최적화만 막아준다
exchange 가 있는 이유는 이 함수로 바꿔야지 prev 에 데이터가 flag 에 변경되어진 값을 스레드 세이프하게 받을수 있음
그렇지 않고
bool prev = flag ; 이렇게 받으면 prev 의 값과 flag 값이 스레드 타이밍상 이 순간에서조차 다른 값일 수 있다
원자적으로 바꾸는 다른 예시..
compare_change-strong 이 함수는 아래 if 처럼 동작한다
'운영체제 & 병렬처리 > Multithread' 카테고리의 다른 글
Walkthrough: Debug a multithreaded app using the Threads window (0) | 2023.01.12 |
---|---|
How to: Flag and Unflag Threads (0) | 2023.01.12 |
MemoryPool 4 : 기존 메모리풀을 MS 로 변경 (0) | 2022.10.13 |
MemoryPool 3 (MS-lock-free stack, ABA 문제 해결방안 128bit) (0) | 2022.10.13 |
MemoryPool 2 (포인터와 인덱스 값으로 ABA 문제 해결방안 128bit) (0) | 2022.10.11 |