728x90
C#으로 작성된 내용입니다.
using System;
namespace ServerStudy
{
class Program
{
static int number = 0;
static void Thread_1()
{
for (int i = 0; i < 100000; i++)
number++;
}
static void Thread_2()
{
for (int i = 0; i < 100000; i++)
number--;
}
static void Main(string[] args)
{
Task t1 = new Task(Thread_1);
Task t2 = new Task(Thread_2);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
Console.WriteLine(number);
}
}
}
이런 코드를 실행시킨다고 생각해보자. 자연스럽게 상상하면 number의 값이 0이 되어야 하지만
실행하면 이런 엉뚱한 숫자가 나온다.
사실 우리가 사용하는 number++, number--는 한 줄로 끝나는 코드가 아니라 여러 실행 단계를 한 줄로 정리해 놓은 것에 불과하다.
int temp = number;
temp += 1;
number = temp;
number++을 풀어 써보면 이런 단계가 나온다. 우리가 만든 코드는 싱글 스레드가 아닌 멀티 스레드다.
즉, number에 1을 더하고 빼는 과정이 따로 일어나는 것이 아니라 동시에 일어나고 있다. Thread_1에서 number에 1을 더한 뒤 number = 1이 된 상황에서 Thread_2가 실행되어 number = 0이 되는 것이 아니다. 늘어나고 줄어들고를 제멋대로 거의 동시에 실행하기 때문에 결과적인 number가 0이 아니게 된다. number++가 3가지 단계를 거치는 것이 아니라 한 줄에 +1을 한다면 이 문제는 사라지게 된다. 이것을 원자성(= atomic 더이상 깨지지 않는 성질) 보증이라 한다.
이때 사용하는 것이 Interlocked다.
static void Thread_1()
{
for (int i = 0; i < 100000; i++)
Interlocked.Increment(ref number);
}
static void Thread_2()
{
for (int i = 0; i < 100000; i++)
Interlocked.Decrement(ref number);
}
number++; 대신 Interlocked.Increment(ref number);를 number--; 대신 Interlocked.Decrement(ref number);를 사용하면
number가 3줄로 나누어서 실행되는 것이 아니라 한 줄로 끝나기 때문에 결국 number는 0이 된다.
728x90
'공부 > 게임 서버' 카테고리의 다른 글
[게임서버] 스핀락(Spinlock)이란? (0) | 2022.05.25 |
---|---|
[게임서버] 상호배제 - Monitor.Enter, Monitor.Exit (0) | 2022.05.24 |
[게임서버] Temporal locality, Spatial locality (0) | 2022.05.23 |
[게임서버] 메모리 배리어(Memory Barrier)란? (0) | 2022.05.23 |
[게임서버] 스레드(Thread)란? (0) | 2022.05.23 |