이 글은 Inflearn - Rookiss : 게임서버 강의를 듣고 정리한 글입니다.
목차.
개요
Interlocked이 무엇인가에 대해 설명하기 앞서
다음 코드의 실행 결과로 어떤 값이 출력될까?
using System;
using System.Numerics;
namespace CSharp
{
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()
{
Task t1 = new Task(Thread_1);
Task t2 = new Task(Thread_2);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
Console.WriteLine(number);
}
}
}
number를 각각 10만 번 더하고 빼주었기 때문에 0이 출력되어야 한다
하지만 실행을 해보면 결과는 그렇지 않다
무작위의 값이 출력되는 것을 볼 수 있다
왜 이런 결과가 나오는 걸까?
우리가 원하는 작업에 대한 결과물은 위 사진과 같을 것이다
number++이라는 작업을 시키면 하나의 스레드가 이를 실행해야 하는데
우리가 작성한 코드를 실행하면
위와 같이 number++이 동시로 작동하기 때문에 0이라는 결과가 나오지 않은 것이다.
number++은 한 줄의 코드지만 내부적으로는 3줄의 코드라고 볼 수 있다.
int temp = num;
temp += 1;
num = temp
위 코드가 number++을 실행시켰을 일어나는 일이다.
그런데 스레드가 동시로 작동하여
위 코드가 동시에 작동한다고 하면 어떤 결과가 나올까?
number가 0이라고 가정해 보겠다.
Thread_1이 실행되었고 number가 1 증가하기 전 Thread_2가 실행되어 버리면 어떤 결과가 나올까?
순서가 정해져 있지 않아 불확실한 결과가 나오게 될 것이다.
그렇다면 코드를 원자적(atomic)으로 실행하기 위해서는 어떻게 해야 할까?
Interlocked 활용
using System;
using System.Numerics;
namespace CSharp
{
class Program {
static int number = 0;
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);
}
}
static void Main()
{
Task t1 = new Task(Thread_1);
Task t2 = new Task(Thread_2);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
Console.WriteLine(number);
}
}
}
위 코드를 실행시켜보면 아까와는 달리 고정적으로 0이라는 결과가 출력된다.
Interlocked는 편리한 기능이지만 성능에서 손해를 볼 수 있다는 점과 거의 정수 부분에서만 사용할 수 있다는 단점이 있다.
Interlocked의 특징은 해당 코드가 실행 중일 때는 절대로 끝나기 전까지 다른 코드가 실행되지 않는다는 특징이 있다.
이러한 이유로 위 코드의 순서가 보장되는 것이다.
Increment/Decrement 외에도
Exchange : 변수의 값을 다른 값으로 교환하고 이전 값을 반환
Compare and Swap : 변수의 현재 값과 지정된 값이 같은 경우에만 새 값을 설정
다음과 같은 기능들이 있습니다.
정리
이 글을 통해 Interlocked의 개념과 사용법에 대해 알아봤습니다.
Interlocked는 멀티스레드 프로그래밍에서 중요한 역할을 하며, 스레드 간의 동기화와 안전성을 보장하는 데 유용합니다.
'프로그래밍 > C#' 카테고리의 다른 글
[C#] 박싱과 언박싱 (0) | 2023.11.09 |
---|---|
[C#] 멀티스레드 프로그래밍 : Interlocked.CompareExchage (0) | 2023.08.09 |
[C#] 멀티스레드 프로그래밍 : Monitor, DeadLock, Lock (0) | 2023.08.08 |
객체지향 소프트웨어 공학 : 객체와 클래스의 개념 (0) | 2023.04.28 |
객체지향 프로그래밍에서의 클래스 이름 규칙 (0) | 2023.04.28 |