C++ atomic

정은성·2023년 3월 16일
0
post-thumbnail

※ Rookiss님의 [C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버 강의를 보고 정리한 글입니다.

atomic??
=> 원자성 ( ALL-Or-Nothing)

int32 sum = 0;

void Add() {
	for (int32 i = 0; i < 100'0000; i++)
	{
		sum++;
	}
}

void Sub() {
	for (int32 i = 0; i < 100'0000; i++)
	{
		sum--;
	}
}

이런 코드가 있다면 싱글 쓰레드 환경에선

Add();
Sub();
cout << sum << endl;

당연히 0이 출력된다.

하지만 멀티쓰레드환경에선

std::thread t1(Add);
std::thread t2(Sub);

t1.join();
t2.join();

cout << sum << endl;

1680651 같은 이상한 숫자가 나오게된다. 심지어 실행을 할 때마다 값이 달라진다.

그 이유는 sum++sum-- 라는 코드가 사실 어셈블리어에선

int eax = sum; // sum++
eax+= 1;
sum = eax;

int eax = sum;
eax -=1;
sum eax;

이런 식으로 이루어져 있기 때문이다. 그래서 Add 와 Sub가 동시에 이루어진다면 1이 증가하고 1이 감소되는 것이아닌 0이란 값에서 증가가 진행되지않고 -1이 될 수 있다는 것이다.

이를 방지하기위한 방법이있다.

윈도우에선 interlocked라는 전용 함수가 있지만 우리는 공용으로 사용되는 atomic을 쓸 것이다.
atomic을 쓰게되면 3개의 단계를 거쳤던 것이 한번에 1을 증가시키는 것으로 끝난다.

#include<atomic>

atomic<int> sum;

사용

사용은 기본적으로 sum++ sum-- 로 가능하지만 이러면 atomic변수인지 일반 변수인지 헷갈릴 수 있기 때문에 이렇게 쓰기도한다.

sum.fetch_add(1);
sum.fetch_add(-1);

더 자세한 내용은 강의 를 참고하자.

0개의 댓글