[Server Programming/cpp] Atomic
thread를 사용할때 전역 변수 공유 문제점
// GameServer.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "pch.h"
#include <iostream>
#include "CorePch.h"
#include <thread>
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()
{
std::thread t1(Add);
std::thread t2(Sub);
t1.join();
t2.join();
cout << sum << endl;
}
결과값이 할때마다 제각각이다.
실제로 sum++이 컴퓨터에서 동작할때 약식으로 아래와 같은 일이 일어난다.
int32 eax = sum;
eax = eax + 1;
sum = eax;
sum--
int32 eax = sum;
eax = eax - 1;
sum = eax;
두 스레드가 각각 동작을 할때 위의 과정이 거의 랜덤으로 각 줄이 실행될 것이다. 그렇다면 한쪽에서 진행하더라도 다른 한쪽에서 sum에 자기 결과값을 최종적으로 넣는다던지..
여러 과정이 섞이고 그게 몇만번 반복되어 엉뚱한 숫자가 등장하게 되는 것.
해결법? Atomic을 이용해서 동기화
위에서 살펴본 sum++의 같은시간에 세가지 과정이 한번에 일어난다면?
깔끔하게 결과값을 적용하여 변경할것이다!
이를 동기화한다고 하며, 그 동기화 기법 중 atomic을 사용해보자.
*atomic: all or nothing (원자성)
#include <atomic>
...
atomic<int32> sum = 0;
...
sum.fetch_add(1); //sum++와 결과가 같지만 atomic을 적용한 변수임을 특정
atomic 결론
- 동기화를 통해 상수적인 결과를 얻을 수 있다.
- 추가 연산으로 속도 저하 발생 가능성 -> 꼭 필요한 경우에만 사용
출처
인프런 Rookiss, "[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버"