어떤 프로세스 안에서 생성된 스레들은 같은 메모리 공간을 공유한다.
스레드가 같은 자원을 공유할 수 있다는 점은 장점이기도 하지만,
반대로 두 스레드가 같은 자원을 동시에 변경하는 경우에는 문제가 된다.
동기화 이슈를 강제로 발생시켜보고
어떻게 막으면 좋을지 한번 찾아보았다.
데이터 레이스 예시
//AI에게 부탁한 코드샘플.
static constexpr int kThreads = 8;
static constexpr int kItersPerT = 2'000'000;
volatile bool gStart = false; // 동시 시작 타이밍 맞추기(간단용)
std::int64_t gShared = 0; // 의도적 데이터 레이스 대상
void RaceWorker()
{
while (!gStart)
{ }
for (int i = 0; i < kItersPerT; ++i)
{
++gShared; // 데이터 레이스!
}
}
int main()
{
std::vector<std::thread> threads;
threads.reserve(kThreads);
for (int i = 0; i < kThreads; ++i)
threads.emplace_back(RaceWorker);
gStart = true; //가시성
for (auto& t : threads)
t.join();
const std::int64_t expected = static_cast<std::int64_t>(kThreads) * kItersPerT;
std::cout << "Expected : " << expected << "\n";
std::cout << "Actual : " << gShared << "\n";
if (gShared != expected)
std::cout << "Race detected (lost updates)\n";
else
std::cout << "No mismatch this run (race may still exist)\n";
return 0;
}

결과는 8개의 스레드가 동시에 접근하면서 데이터 레이스가 발생했다.
이러한 이슈들을 막기 위해 동기화 도구들이 필요하다.
복합연산 이 연산은 단순한 더하기 연산 같지만,
++gShared; // 데이터 레이스!
내부적으로는 아래 load, add, store 3단계가 존재한다.
1. 메모리에서 gShared 읽기 (load)
2. 값 + 1 계산 (add)
3. 메모리에서 다시 쓰기 (store)
예를들어, 스레드A가 gShared를 add하고 있는 상태에서
또 스레드B가 add를 할 수 있는 상황이 발생 할 수 있다.
그러면 데이터 레이스가 생긴다.
Lock
대표적으로 락이다. 공유 자원에 붙이면 해당 자원에 대한 접근을 동기화할 수 있다.
스레드가 해당 자원을 접근하려면 우선 그 자원에 붙어 있는 락을 획득 해야한다.
락은 한 스레드만 쥐고 있을 수 있다.
그래서 공유 자원은 한 번에 한 스레드만 사용할 수 있게 하는것이다.
lock은 스레드 전환에 컨텍스트 스위칭과 데드락에 위험이 존재한다.
std::mutex gMutex;
void RaceWorker()
{
while (!gStart)
{ }
for (int i = 0; i < kItersPerT; ++i)
{
std::lock_guard<std::mutex> lock(gMutex);
++gShared;
}
}

atomic 연산자
std::atomic<std::int64_t> gShared = 0;
void RaceWorker()
{
while (!gStart)
{ }
for (int i = 0; i < kItersPerT; ++i)
{
++gShared; // 데이터 레이스!
}
}

아토믹 연산자를 사용하면 lock없이도 데이터 레이스를 방지할 수 있다.
아토믹 연산자는 load, add, store하는 3단계가 아닌
CPU레벨에서 하나의 원자 연산으로 보장된다.
lock없이도 데이터 레이스에 피할 수 있지만,
여러 변수,조건 + 분기, 컨테이너 조작에 대해서는 적합하지 않다.
오늘 포스팅한 샘플처럼 카운트 수정이나
단일 변수 수정에 적합하다.
'STUDY > 운영체제' 카테고리의 다른 글
| OS) 시스템 콜이란? (System Call) (0) | 2026.01.22 |
|---|---|
| [컴퓨터 구조] 캐시이론 Locality (0) | 2021.09.23 |
| 운영체제) 교착상태 (deadlock) (0) | 2019.08.16 |