for( 백만번 )
i++;
for(백만번)
i--;
해주면 결과적으로는 0이 되어야 하는데
멀티 쓰레딩 환경에서는 그 값을 예측할 수 없다.
cpu 설계상의 이유로
i++ 은 우리한테는 한 줄짜리 코드인데
디스어셈블 해보면 아래와 같은 명령어로 실행 된다.
int32 eax = sum;
eax = eax +1;
sum = eax;
이 과정에서 공용자원인 i가 서로 건드리기 때문이다.
운영체제마다 라이브러리가 다르지만 windows 에는 interlockedAdd() 가 있지만
MordernC++ 표준에서는 #include<atomic> 으로 어지간해서 통합해서 사용하면 된다.
#include<atomic>
atomic<int32> sum = 0;
이제 sum을 누군가 사용하면 ALL-OR-Nothing 방식으로 실행된다.
내부적으로 어떻게 돌아가냐면 만약에 쓰레드들끼리 경합을 해서 ++를 실행하는 쓰레드가 간발의 차이로 먼저 실행했다고 한다면 사실상 경합에서 진 -- 쓰레드는 실행되지 않는다. (완료가 될때까지 살짝 대기를 하게 된다.)
그리고 그 순서는 CPU가 관리한다.
인스트럭션이 CPU단에 있다. 그래서 해당 sum 메모리로의 접근을 막을 수 있다.
아 그럼 멀티쓰레드 환경에서는 무조건 Atomic 변수를 사용하면 되겠다???
당연한 말이겠지만 atomic 계열을 사용하면 연산이 정말 느리다. 그래서 정말로 필요할 때만 사용해야한다.
그리고 하나가 실행중일때 다른 쓰레드가 조금이라도 기다리니깐 병목현상이 생길 수 도 있다.
앞으로 배울 여러 동기화 방법중 첫번째 동기화 방법이다.
'C++과 언리얼로 만드는 게임 개발 > Part4. Server' 카테고리의 다른 글
★(중요_다시듣기)★DeadLock | V (0) | 2022.04.28 |
---|---|
lock 동기화 방법(2) | V (0) | 2022.04.27 |
쓰레드 생성 | V (0) | 2022.04.15 |
환경 설정 (0) | 2022.04.12 |
서버 OT (0) | 2022.04.12 |