쓰레드간 공유할 수 있는 메모리 영역 : 힙, 데이터 영역
스택영역의 데이터는 공유 못한다.
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--;
}
}
int main()
{
Add();
Sub();
cout << sum << endl;
std::thread t1(Add);
std::thread t2(Sub);
t1.join();
t2.join();
cout << sum << endl;
}
위 코드를 실행하면 두 개의 쓰레드로 실행했을 때 값이 이상하게 출력된다.
이유는 sum++, sum-- 코드가 한 번에 실행되지 않고 여러 명령에 걸쳐 실행되기 때문이다.
디스어셈블하여 보면
{
sum++;
00007FF746902765 mov eax,dword ptr [sum (07FF74690F440h)]
00007FF74690276B inc eax
00007FF74690276D mov dword ptr [sum (07FF74690F440h)],eax
}
세 개의 명령어로 실행된다. 결국 연산결과가 공유 메모리인 sum에 덮어씌여진다. 이 때문에 이상한 결과가 나온다.
이를 해결하기 위해 std::atomic을 사용할 수 있다.
atomic 연산은 한 번에 하나의 명령만 수행하고 만약 같은 메모리에 연산을 수행하려하면 대기시킨다.
따라서 정확한 값을 얻을 수 있다. 그러나 연산속도가 느리므로 모든 메모리 공유 상황에서 atomic을 쓰는 건 성능 저하를 불러 일으킨다.
참조 : [C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버 - 인프런 | 강의 (inflearn.com)
댓글 영역